ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ ΜΑΘΗΜΑ 9 Ο Διαχείριση αλφαριθμητικών και πράξεις σε επίπεδο bit 1
Εισαγωγή Τα αλφαριθμητικά δεδομένα καταλαμβάνουν σημαντικότατη θέση στον προγραμματισμό, ιδιαίτερα σε εφαρμογές εμπορικές και γραφείου. Ωστόσο βρίσκουν εφαρμογή και σε κάθε περίπτωση που δημιουργούνται αυτόματα τυποποιημένα ονόματα αρχείων. Θα μελετηθούν στη συνέχεια οι συναρτήσεις που χειρίζονται τέτοια αλφαριθμητικά δεδομένα, συνθέτοντας, αποκόπτοντας μετατρέποντάς τα. Επίσης σημαντικότατο θέμα αποτελεί η επεξεργασία δεδομένων σε επίπεδο bit. Ο προγραμματισμός στο επίπεδο αυτό δίνει τη δυνατότητα επέμβασης σε ρυθμίσεις υλικού μέρους (Hardware) συσκευών και συνεργασίας με τις θύρες επικοινωνίας. Θα μελετηθούν οι τελεστές Bitwise & λογικής σύζευξης, λογικής διάζευξης, ^ αποκλειστικής διάζευξης και ~ συμπληρώματος ως προς 1 και οι τελεστές μετατόπισης << και >> 2
Αλφαριθμητικά Μέχρι εδώ έχουμε ασχοληθεί κυρίως με αριθμητικά δεδομένα και από χαρακτήρες απλώς ορίσαμε τον τύπο char και αναφερθήκαμε στις συναρτήσεις getchar(), putchar(), gets() και puts() που χειρίζονται οι πρώτες μεμονωμένους χαρακτήρες ενώ οι επόμενες δυο σειρά χαρακτήρων. Η δήλωση σειράς χαρακτήρων, συμβολοσειράς, string γίνεται με τη αξιοποίηση κάποιας δομής π.χ. πίνακα τόσον θέσεων όσο είναι ο αριθμός των χαρακτήρων της σειράς. Η δήλωση char string1[50] σημαίνει ότι η μεταβλητή string1 μπορεί να περιέχει μια συμβολοσειρά 49 χαρακτήρων γιατί την τελευταία θέση την χρησιμοποιεί για τον χαρακτήρα null που δηλώνει το τέλος της σειράς. Οι πιο σημαντικές συναρτήσεις διαχείρισης αλφαριθμητικών είναι strlen(s), strcpy(dst, src), strncpy(dst, src, n), strncat(dst, src, n), strcat(dst, src), strcmp(s1,s2), strchr(s,ch), strrchr(s,ch) και strstr(s1,s2) 3
strlen(s), strcpy(d, sr) και strcat(d, sr) Οι συναρτήσεις διαχείρισης αλφαριθμητικών περιέχονται στην βιβλιοθήκη <string.h> επομένως πρέπει να συμπεριληφθεί σε κάθε πρόγραμμα που τις χρησιμοποιεί. Ειδικότερα η strlen(s) επιστρέφει τον συνολικό αριθμό χαρακτήρων που περιέχονται στην αλφαριθμητική μεταβλητή s. Η strcpy(dst, src) αντιγράφει την μεταβλητή src στην dst. Για την αντιγραφή αυτή θα πρέπει να προβλεφθεί ότι η dst θα έχει ορισθεί ως χαρακτήρων με τουλάχιστον μία θέση μεγαλύτερη της src. Να σημειωθεί ότι δεν μπορεί να ανατεθεί το περιεχόμενο της src στην dst με την απλή ανάθεση dst=str; Ο μόνος τρόπος να γίνει αυτό είναι με τη χρήση της strcpy(dst, src); Ησυνάρτησηstrncpy(dst, src, n) αποτελεί βελτίωση της προηγούμενης γιατί αντιγράφει τους n πρώτους χαρακτήρες της src στην dst Ησυνάρτησηstrcat(dst, src) συνενώνει το αλφαριθμητικό src με το dst στο οποίο αποθηκεύεται και η νέα τιμή. Έτσι δημιουργούνται αλφαριθμητικά συνενώνοντας κατάλληλα επιμέρους τμήματα. Η συνάρτηση strncat(dst, src, n) αποτελεί βελτίωση της προηγούμενης γιατί συνενώνει τους n πρώτους χαρακτήρες της src στην dst. 4
strcmp(s1,s2), strchr(s,ch) και strstr(s1,s2) Ησυνάρτησηstrcmp(s1,s2) συγκρίνει τα δύο αλφαριθμητικά s1 και s2. Συγκρίνει τις δύο αλφαριθμητικές μεταβλητές και επιστρέφει την τιμή 0 αν τα αλφαριθμητικά είναι πιστά ίδια, αρνητική τιμή αν το s1 είναι μικρότερο του s2 και αντίθετα θετική τιμή αν το s1 είναι μεγαλύτερο του s2. Η σύγκριση γίνεται λεξικογραφικά. Δηλαδή ανάλογα με το πώς θα εμφανιζόταν σε αλφαβητική ταξινόμηση. Πρέπει να σημειωθεί ότι οι πεζοί χαρακτήρες είναι μεγαλύτεροι των κεφαλαίων. Η συνάρτηση strchr(s,ch) εντοπίζει τον χαρακτήρα ch στην συμβολοσειρά s και αν τον εντοπίσει, επιστρέφει δείκτη που δείχνει προς τον χαρακτήρα αυτό. Να σημειωθεί ότι η αναζήτηση γίνεται από αριστερά προς τα δεξιά. Για αναζήτηση από το τέλος προς την αρχή χρησιμοποιείται η συνάρτηση strrchr(s,ch). Αν αναζητείται ολόκληρο αλφαριθμητικό μέσα σε άλλο τότε χρησιμοποιείται η strstr(s1,s2) η οποία επιστρέφει δείκτη που δείχνει προς τον αλφαριθμητικό s2. Ουσιαστικά το αποτέλεσμά της είναι ότι και η strchr(s,ch) βελτιωμένη για την αναζήτηση σειράς χαρακτήρων και όχι μεμονωμένου χαρακτήρα. 5
Δυαδική παράσταση Είναι γνωστό ότι η λειτουργία του ηλεκτρονικού υπολογιστή αλλά και η διαχείριση των δεδομένων από αυτόν γίνονται με την κωδικοποίησή τους σε δυαδική μορφή. Από την άλλη πλευρά επειδή ως βασική μονάδα μνήμης χρησιμοποιείται το byte που είναι σύνολο οκτώ bit στην αναπαράσταση των δεδομένων χρησιμοποιούνται πολλαπλάσιά του ακόμα και όταν δεν χρειάζονται. Από την άλλη η επεξεργασία τους απαιτεί τον χειρισμό bytes και πολλές φορές πολλαπλασίων του. Με την επεξεργασία σε επίπεδο bit μπορούν να γίνουν απίστευτα λεπτοί χειρισμοί και πολύ γρήγορες ορισμένες πράξεις. Για παράδειγμα με τους τελεστές μετατόπισης μπορούν να μετατοπίζονται τα bits προς τα αριστερά συγκεκριμένο αριθμό θέσεων, ας υποθέσουμε n. Αυτό σημαίνει ότι ο αρχικός αριθμός πολλαπλασιάζεται με το 2 n. Αντίθετα μετατόπιση προς τα δεξιά σημαίνει διαίρεση με το 2 n. Να σημειωθεί ότι τα αποτελέσματα πολλαπλασιασμού και διαίρεσης θα είναι συμβατά με τις προϋποθέσεις των δεδομένων που χειρίζεται. 6
Bitwise τελεστές Οι τελεστές που χειρίζονται τα bit ενεργούν στους τύπους δεδομένων char, int, short, long, signed και unsigned και είναι : x<< n x>> n x 1 &x 2 Μετατοπίζει προς τα αριστερά τα bit κατά n θέσεις π.χ. x=56<<2 το γίνεται x=224 από 00111000 γίνεται 11100000 Μετατοπίζει προς τα δεξιά τα bit κατά n θέσεις π.χ. x=56>>2 το γίνεται x=14 από 00111000 γίνεται 00001110 Κάνει λογική σύγκριση. Το αποτέλεσμά του είναι 1 μόνο στα bits που είναι 1 και στις δύο συγκρινόμενες τιμές. x 1 Ix 2 Κάνει λογική σύγκριση. Το αποτέλεσμά του είναι 1 στα bits που είναι 1 τουλάχιστον σε μία από τις συγκρινόμενες τιμές. x 1^x 2 ~x Θέτει 1 στα bits που είναι διαφορετικά στις δύο συγκρινόμενες τιμές. Αντιστρέφει τις τιμές των bits. Το bit με τιμή 0 γίνεται 1 και αντίστροφα. Βρίσκει δηλαδή το συμπλήρωμα ως προς 1. 7
Μάσκα Για την διαχείριση των bits σε μια μεταβλητή χρησιμοποιούμε την λογική της μάσκας που συνδυάζεται με τους κατάλληλους Bitwise τελεστές. Ο τελεστής & χρησιμοποιείται με την κατάλληλη μάσκα για να απενεργοποιηθούν συγκεκριμένα bits της μεταβλητής. Ο τελεστής χρησιμοποιείται με την κατάλληλη μάσκα για να ενεργοποιηθούν συγκεκριμένα bits της μεταβλητής. Ο τελεστής ^ χρησιμοποιείται με την κατάλληλη μάσκα για να εναλλάξει συγκεκριμένα bits της μεταβλητής και να αφήσει αμετάβλητα άλλα. Ο τελεστής ~ χρησιμοποιείται για να εναλλάξει όλα τα bits της μεταβλητής. Παράδειγμα δυαδική μορφή του 75, που έχει ορισθεί ως char, μπορεί να χρησιμοποιηθεί ως αρχική μάσκα το 128 η οποία διαδοχικά μεταβάλλεται με δεξιά μετατόπιση κατά 1 θέση κάθε φορά. Έτσι με το 75 & μάσκα θα δώσει το αποτέλεσμα σε δυαδική μορφή. Αρχική μάσκα 10000000, επόμενη 01000000, 00100000, 00010000, 00001000, 00000100, 00000010 και 00000001 οπότε το 75 & μάσκα θα εμφανίσει 1 εκεί που η δυαδική παράσταση του 75 έχει 1. 8