Δείκτες Προγραμματισμός Ι lalis@inf.uth.gr
Δείκτες Υπάρχουν περιπτώσεις που δεν ενδιαφέρει το περιεχόμενο αλλά η διεύθυνση μιας μεταβλητής. Χρειάζεται κατάλληλος μηχανισμός αναφοράς και επεξεργασίας τιμών που είναι διευθύνσεις μνήμης. Υπάρχουν μεταβλητές ειδικού τύπου: δείκτες. Μια μεταβλητή δείκτης μπορεί να χρησιμοποιηθεί για την αποθήκευση μιας ακέραιας τιμής που ερμηνεύεται σαν διεύθυνση μνήμης. Μέσω μιας μεταβλητής δείκτη μπορούμε να διαβάσουμε και να αλλάξουμε την τιμή που βρίσκεται αποθηκευμένη στην διεύθυνση που αυτή περιέχει. Προγραμματισμός Ι lalis@inf.uth.gr
Δείκτες και τύποι δεδομένων Η έννοια του δείκτη μπορεί να εφαρμοστεί σε κάθε τύπο Τ για να οριστεί ο τύπος δείκτης-σε-Τ. Υπάρχει συντακτική συμβατότητα ανάμεσα: στην τιμή που βρίσκεται στην διεύθυνση που περιέχει μια μεταβλητή δείκτης-σε-Τ και την τιμή μιας μεταβλητής τύπου Τ στην τιμή μιας μεταβλητής δείκτης-σε-Τ και την διεύθυνση μιας μεταβλητής τύπου Τ Η ειδική τιμή NULL (0) σημαίνει «καμία διεύθυνση», και είναι η συνηθισμένη τιμή αρχικοποίησης μιας μεταβλητής δείκτη. Η προσπάθεια προσπέλασης της διεύθυνσης 0 έχει σαν αποτέλεσμα τον τερματισμό του προγράμματος. Προγραμματισμός Ι lalis@inf.uth.gr
Τελεστές που αφορούν δείκτες Ο τελεστής & (reference) εφαρμόζεται σε μια μεταβλητή και επιστρέφει την διεύθυνση της. Ο τελεστής * (dereference) εφαρμόζεται σε μια μεταβλητή δείκτη-σε-Τ ώστε αυτή να ερμηνευτεί σαν μεταβλητή τύπου Τ – μπορεί να χρησιμοποιηθεί σε οποιαδήποτε έκφραση αποτίμησης ή/και ανάθεσης όπου αναμένεται μια μεταβλητή (ή τιμή) τύπου Τ. Μέσω ενός δείκτη που περιέχει την διεύθυνση μιας (συμβατικής) μεταβλητής μπορούμε να διαβάσουμε / αλλάξουμε έμμεσα την τιμή της μεταβλητής, χωρίς να φαίνεται στον κώδικα το όνομα της. Αυτό είναι μια μορφή παρενέργειας! Προγραμματισμός Ι lalis@inf.uth.gr
int *b,*c; /* δείκτες σε ακέραιο b,c */ a = 1; int a; /* ακέραιος a */ int *b,*c; /* δείκτες σε ακέραιο b,c */ a = 1; b = &a; /* b γίνεται διεύθυνση του a */ *b = 2; /* a γίνεται 2 */ *b = *b+1; /* a γίνεται 3 */ c = b; /* c γίνεται διεύθυνση του a */ *c = *c+2; /* a γίνεται 5 */ Προγραμματισμός Ι lalis@inf.uth.gr
διεύθυνση περιεχόμενα 1 1 1 1 1 1 1 1 2 1 1 1 1 1 3 1 1 1 1 1 4 1 1 1 … char a; 1 1 1 1 a 1 1 1 1 2 1 1 1 1 1 3 1 1 1 1 1 4 1 1 1 1 5 1 1 1 1 1 1 6 1 1 1 1 1 1 7 1 1 1 1 1 1 8 1 1 1 1 1 1 ................ Προγραμματισμός Ι lalis@inf.uth.gr
διεύθυνση περιεχόμενα 1 1 1 1 1 1 1 1 2 1 1 1 1 1 3 1 1 1 1 1 4 1 1 1 … char a; char *b; 1 1 1 1 a 1 1 1 1 2 1 1 1 1 1 3 1 1 1 1 1 4 1 1 1 1 5 1 1 1 1 1 1 b 6 1 1 1 1 1 1 7 1 1 1 1 1 1 8 1 1 1 1 1 1 ................ Προγραμματισμός Ι lalis@inf.uth.gr
διεύθυνση περιεχόμενα 1 1 1 1 1 1 1 1 2 1 1 1 3 1 1 1 1 1 1 1 1 4 1 1 … char a; char *b; a='a'; 1 1 1 1 a 1 1 1 1 2 1 1 1 3 1 1 1 1 1 1 1 1 4 1 1 1 1 5 1 1 1 1 1 1 b 6 1 1 1 1 1 1 7 1 1 1 1 1 1 8 1 1 1 1 1 1 ................ Προγραμματισμός Ι lalis@inf.uth.gr
διεύθυνση περιεχόμενα 1 1 1 1 1 1 1 1 2 1 1 1 3 1 1 1 1 1 1 1 1 4 1 1 … char a; char *b; a='a'; b=&a; 1 1 1 1 a 1 1 1 1 2 1 1 1 3 1 1 1 1 1 1 1 1 4 1 1 1 1 5 1 b 6 7 8 ................ Προγραμματισμός Ι lalis@inf.uth.gr
διεύθυνση περιεχόμενα 1 1 1 1 1 1 1 1 2 1 1 1 3 4 1 1 1 1 5 1 6 7 8 … char a; char *b; a='a'; b=&a; *b='b'; 1 1 1 1 a 1 1 1 1 2 1 1 1 3 4 1 1 1 1 5 1 b 6 7 8 ................ Προγραμματισμός Ι lalis@inf.uth.gr
Παράκαμψη συντακτικού ελέγχου Ο συντακτικός έλεγχος μπορεί να παρακαμφθεί με χρήση type casting (δηλωμένης μετατροπής τύπου), έτσι ώστε μια οποιαδήποτε ακέραια τιμή να ανατεθεί (χωρίς μετατροπή) σε μια μεταβλητή δείκτη. Επιτρέπεται αριθμητική με δείκτες, π.χ. αν p είναι μια μεταβλητή δείκτης-σε-Τ, τότε η έκφραση p+i μεταφράζεται (αυτόματα) ως p+i*sizeof(T). Δεν υπάρχει τρόπος για τον μεταφραστή να ελέγξει αν μια τιμή που ανατίθεται σε μια μεταβλητή δείκτη-σε-Τ (μέσω type cast ή αριθμητικής) αντιστοιχεί πραγματικά στη διεύθυνση ενός αντικειμένου Τ. Την ευθύνη ανάθεσης κατάλληλων τιμών σε μεταβλητές δείκτη την έχει ο προγραμματιστής. Προγραμματισμός Ι lalis@inf.uth.gr
short int a; /* ακέραιος a (έστω 2 bytes) */ char *b; /* δείκτης σε χαρακτήρα b */ b=(char*)&a; /* b γίνεται διεύθυνση του a, αλλά η πρόσβαση μέσω b γίνεται με βάση τον τύπο char, ανά byte */ *b = *b+1; /* το πρώτο byte του a αυξάνεται κατά 1 */ b++; /* b γίνεται διεύθυνση του a + 1 */ *b = *b+1; /* το δεύτερο byte του a αυξάνεται κατά 1 */ b++; /* b γίνεται διεύθυνση του a + 2 */ *b = *b+1; /* το τρίτο(;) byte του a αυξάνεται κατά 1 */ Προγραμματισμός Ι lalis@inf.uth.gr
υποθέτουμε μέγεθος short 2 bytes 1 1 1 1 7 1 1 1 1 1 1 8 short int i; … char *c; διεύθυνση περιεχόμενα 1 1 1 1 1 1 1 1 1 2 1 3 1 1 1 1 4 1 1 1 1 5 1 1 1 1 6 υποθέτουμε μέγεθος short 2 bytes 1 1 1 1 7 1 1 1 1 1 1 8 ................ Προγραμματισμός Ι lalis@inf.uth.gr
short int i; … char *c; i=0x6261; διεύθυνση περιεχόμενα 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 1 3 1 1 1 1 4 1 1 1 1 5 1 1 1 1 6 1 1 1 1 7 1 1 1 1 1 1 8 ................ Προγραμματισμός Ι lalis@inf.uth.gr
short int i; … char *c; i=0x6261; c = (char *) &i; διεύθυνση περιεχόμενα 1 1 1 1 1 1 1 1 2 1 3 4 5 6 7 1 1 1 1 1 1 8 ................ Προγραμματισμός Ι lalis@inf.uth.gr
putchar(*c); /* -> 'a' */ διεύθυνση περιεχόμενα short int i; … char *c; i=0x6261; c = (char *) &i; putchar(*c); /* -> 'a' */ διεύθυνση περιεχόμενα 1 1 1 1 1 1 1 1 2 1 3 4 5 6 7 1 1 1 1 1 1 8 ................ Προγραμματισμός Ι lalis@inf.uth.gr
putchar(*c); /* -> 'a' */ c++; διεύθυνση περιεχόμενα short int i; … char *c; i=0x6261; c = (char *) &i; putchar(*c); /* -> 'a' */ c++; διεύθυνση περιεχόμενα 1 1 1 1 1 1 1 1 2 1 3 1 4 5 6 7 1 1 1 1 1 1 8 ................ Προγραμματισμός Ι lalis@inf.uth.gr
putchar(*c); /* -> 'a' */ c++; putchar(*c); /* -> 'b' */ short int i; … char *c; i=0x6261; c = (char *) &i; putchar(*c); /* -> 'a' */ c++; putchar(*c); /* -> 'b' */ διεύθυνση περιεχόμενα 1 1 1 1 1 1 1 1 2 1 3 1 4 5 6 7 1 1 1 1 1 1 8 ................ Προγραμματισμός Ι lalis@inf.uth.gr
putchar(*c); /* -> 'a' */ c++; putchar(*c); /* -> 'b' */ short int i; … char *c; i=0x6261; c = (char *) &i; putchar(*c); /* -> 'a' */ c++; putchar(*c); /* -> 'b' */ *c = *c + 1; διεύθυνση περιεχόμενα 1 1 1 1 1 1 1 1 1 2 1 3 1 4 5 6 7 1 1 1 1 1 1 8 ................ Προγραμματισμός Ι lalis@inf.uth.gr
putchar(*c); /* -> 'a' */ c++; putchar(*c); /* -> 'b' */ short int i; … char *c; i=0x6261; c = (char *) &i; putchar(*c); /* -> 'a' */ c++; putchar(*c); /* -> 'b' */ *c = *c + 1; putchar(*c); /* -> 'c' */ διεύθυνση περιεχόμενα 1 1 1 1 1 1 1 1 1 2 1 3 1 4 5 6 7 1 1 1 1 1 1 8 ................ Προγραμματισμός Ι lalis@inf.uth.gr
putchar(*c); /* -> 'a' */ c++; putchar(*c); /* -> 'b' */ short int i; … char *c; i=0x6261; c = (char *) &i; putchar(*c); /* -> 'a' */ c++; putchar(*c); /* -> 'b' */ *c = *c + 1; putchar(*c); /* -> 'c' */ printf("%x",i); /* 6361 */ διεύθυνση περιεχόμενα 1 1 1 1 1 1 1 1 1 2 1 3 1 4 5 6 7 1 1 1 1 1 1 8 ................ Προγραμματισμός Ι lalis@inf.uth.gr
putchar(*c); /* -> 'a' */ c++; putchar(*c); /* -> 'b' */ short int i; … char *c; i=0x6261; c = (char *) &i; putchar(*c); /* -> 'a' */ c++; putchar(*c); /* -> 'b' */ *c = *c + 1; putchar(*c); /* -> 'c' */ printf("%x",i); /* 6361 */ διεύθυνση περιεχόμενα 1 1 1 1 1 1 1 1 1 2 1 3 1 4 5 6 7 1 1 1 1 1 1 8 ................ Προγραμματισμός Ι lalis@inf.uth.gr
putchar(*c); /* -> 'a' */ c++; putchar(*c); /* -> 'b' */ short int i; … char *c; i=0x6261; c = (char *) &i; putchar(*c); /* -> 'a' */ c++; putchar(*c); /* -> 'b' */ *c = *c + 1; putchar(*c); /* -> 'c' */ printf("%x",i); /* 6361 */ *c = 0xFF; διεύθυνση περιεχόμενα 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 1 3 1 4 5 6 7 1 1 1 1 1 1 8 ................ Προγραμματισμός Ι lalis@inf.uth.gr
Προσοχή Η ανάθεση τιμών σε μεταβλητές δείκτες γίνεται με αποκλειστική ευθύνη του προγραμματιστή, χωρίς να γίνεται κάποιος (ολοκληρωμένος) έλεγχος από τον μεταφραστή. Το παραμικρό λάθος όταν χρησιμοποιούμε δείκτες, μπορεί να οδηγήσει σε απρόβλεπτα αποτελέσματα. Χωρίς να το επιθυμούμε (ούτε να το αντιληφθούμε) μπορεί να αλλάξουμε κατά λάθος τιμές μεταβλητών, ακόμα και μεταβλητών-δεικτών ... Όπως και στην παράβαση των ορίων ενός πίνακα, τέτοια σφάλματα δύσκολα εντοπίζονται – αν έχουμε τύχη, τερματίζεται η εκτέλεση του προγράμματος. Προγραμματισμός Ι lalis@inf.uth.gr
Δείκτες και πίνακες Μια μεταβλητή «πίνακας από αντικείμενα τύπου Τ» μπορεί να θεωρηθεί ως (είναι συντακτικά συμβατή με) μια μεταβλητή «δείκτης-σε-Τ» με σταθερή τιμή την διεύθυνση του πρώτου στοιχείου του πίνακα. Αντίστροφα, μια μεταβλητή δείκτης-σε-Τ (και μια διεύθυνση μεταβλητής τύπου Τ) μπορεί να θεωρηθεί ως η αρχή ενός πίνακα από αντικείμενα τύπου Τ. Με χρήση δεικτών μπορεί να γίνει διέλευση των στοιχείων ενός πίνακα – αντί της συμβατικής μεθόδου πρόσβασης μέσω της θέσης τους. Υπάρχει συντακτική συμβατότητα ανάμεσα σε μεταβλητές «πίνακας από Τ» και «δείκτης σε Τ». Προγραμματισμός Ι lalis@inf.uth.gr
int a[5]; int * b = a; a[0] a[1] a[2] a[3] a[4] *b *(b+1) *(b+2) Προγραμματισμός Ι lalis@inf.uth.gr
διεύθυνση περιεχόμενα 1 1 1 1 1 1 1 1 2 1 1 1 3 1 1 1 1 4 1 1 5 1 1 1 … char a[]={'a','b','c'}; 1 1 1 1 1 1 1 1 2 1 1 1 a[0] 3 1 1 1 1 a[1] 4 1 1 a[2] 5 1 1 1 1 1 1 6 1 1 1 1 1 1 7 1 1 1 1 1 1 8 1 1 1 1 1 1 ................ Προγραμματισμός Ι lalis@inf.uth.gr
διεύθυνση περιεχόμενα 1 1 1 1 1 1 1 1 2 1 1 1 3 1 1 1 1 4 1 1 5 1 6 7 … char a[]={'a','b','c'}; char *b=a; 1 1 1 1 1 1 1 1 2 1 1 1 a[0] 3 1 1 1 1 a[1] 4 1 1 a[2] 5 1 6 b 7 8 ................ Προγραμματισμός Ι lalis@inf.uth.gr
διεύθυνση περιεχόμενα 1 1 1 1 1 1 1 1 2 1 1 1 3 1 1 1 1 4 1 1 5 1 6 7 … char a[]={'a','b','c'}; char *b=a; b[0]++; 1 1 1 1 1 1 1 1 2 1 1 1 a[0] 3 1 1 1 1 a[1] 4 1 1 a[2] 5 1 6 b 7 8 ................ Προγραμματισμός Ι lalis@inf.uth.gr
διεύθυνση περιεχόμενα 1 1 1 1 1 1 1 1 2 1 1 1 1 3 1 1 1 1 4 1 1 5 1 6 … char a[]={'a','b','c'}; char *b=a; b[0]++; b[1]++; 1 1 1 1 1 1 1 1 2 1 1 1 1 a[0] 3 1 1 1 1 a[1] 4 1 1 a[2] 5 1 6 b 7 8 ................ Προγραμματισμός Ι lalis@inf.uth.gr
διεύθυνση περιεχόμενα 1 1 1 1 1 1 1 1 2 1 1 1 1 3 1 1 1 4 1 1 5 1 6 7 … char a[]={'a','b','c'}; char *b=a; b[0]++; b[1]++; b[2]++; 1 1 1 1 1 1 1 1 2 1 1 1 1 a[0] 3 1 1 1 a[1] 4 1 1 a[2] 5 1 6 b 7 8 ................ Προγραμματισμός Ι lalis@inf.uth.gr
διεύθυνση περιεχόμενα 1 1 1 1 1 1 1 1 1 2 1 1 1 1 3 1 1 1 4 1 1 1 5 1 … char a[]={'a','b','c'}; char *b=a; b[0]++; b[1]++; b[2]++; *b=*b+1; 1 1 1 1 1 1 1 1 1 2 1 1 1 1 a[0] 3 1 1 1 a[1] 4 1 1 1 a[2] 5 1 6 b 7 8 ................ Προγραμματισμός Ι lalis@inf.uth.gr
διεύθυνση περιεχόμενα 1 1 1 1 1 1 1 1 1 2 1 1 1 1 3 1 1 1 4 1 1 1 5 1 … char a[]={'a','b','c'}; char *b=a; b[0]++; b[1]++; b[2]++; *b=*b+1; b++; 1 1 1 1 1 1 1 1 1 2 1 1 1 1 a[0] 3 1 1 1 a[1] 4 1 1 1 a[2] 5 1 6 b 7 8 ................ Προγραμματισμός Ι lalis@inf.uth.gr
διεύθυνση περιεχόμενα 1 1 1 1 1 1 1 1 1 2 1 1 1 3 1 1 1 4 1 1 1 5 1 6 … char a[]={'a','b','c'}; char *b=a; b[0]++; b[1]++; b[2]++; *b=*b+1; b++; 1 1 1 1 1 1 1 1 1 2 1 1 1 a[0] 3 1 1 1 a[1] 4 1 1 1 a[2] 5 1 6 b 7 8 ................ Προγραμματισμός Ι lalis@inf.uth.gr
διεύθυνση περιεχόμενα 1 1 1 1 1 1 1 1 1 2 1 1 1 3 1 1 1 4 1 1 1 5 1 1 … char a[]={'a','b','c'}; char *b=a; b[0]++; b[1]++; b[2]++; *b=*b+1; b++; 1 1 1 1 1 1 1 1 1 2 1 1 1 a[0] 3 1 1 1 a[1] 4 1 1 1 a[2] 5 1 1 6 b 7 8 ................ Προγραμματισμός Ι lalis@inf.uth.gr
διεύθυνση περιεχόμενα 1 1 1 1 1 1 1 1 1 2 1 1 1 3 1 1 1 1 4 1 1 1 5 1 … char a[]={'a','b','c'}; char *b=a; b[0]++; b[1]++; b[2]++; *b=*b+1; b++; 1 1 1 1 1 1 1 1 1 2 1 1 1 a[0] 3 1 1 1 1 a[1] 4 1 1 1 a[2] 5 1 1 6 b 7 8 ................ Προγραμματισμός Ι lalis@inf.uth.gr
/* εκτύπωση strings αποθηκευμένων σε ένα πίνακα */ char s[]= {'o','n','e','\0','t','w','o','\0','x'}; char *p; printf("%s\n", s); /* εκτυπώνει "one" */ printf("%s\n", &s[0]); /* εκτυπώνει "one" */ p = s; printf("%s\n", p); /* εκτυπώνει "one" */ printf("%s\n", &s[4]); /* εκτυπώνει "two" */ p = p + 4; printf("%s\n", p); /* εκτυπώνει "two" */ printf("%s\n", p + 1); /* εκτυπώνει "wo" */ Προγραμματισμός Ι lalis@inf.uth.gr
Σχόλιο Η πρόσβαση σε στοιχεία του πίνακα με δείκτη μπορεί να είναι πιο γρήγορη από την συμβατική πρόσβαση μέσω θέσης στον πίνακα – γιατί; Δεν είναι καλή ιδέα να χρησιμοποιείται, εκτός και αν υπάρχει σοβαρός λόγος, π.χ. η συγκεκριμένη πρόσβαση αποτελεί όντως σημείο συμφόρησης ενός ιδιαίτερα κρίσιμου κώδικα. Σε γενικές γραμμές, η συμβατική πρόσβαση στα στοιχεία ενός πίνακα βελτιώνει την αναγνωσιμότητα του κώδικα. Η πρόσβαση με δείκτες είναι συνήθης τακτική ιδίως για προγραμματισμό σε «χαμηλό» επίπεδο συστήματος π.χ. λειτουργικό σύστημα. Προγραμματισμός Ι lalis@inf.uth.gr
/* διέλευση (εκτύπωση) πίνακα ακεραίων */ int i,a[N]; for (i=0; i<N; i++) { printf("%d ",a[i]); } printf("\n"); /* διέλευση (εκτύπωση) πίνακα ακεραίων */ int i,*p,a[N]; p=a; for (i=0; i<N; i++) { printf("%d ",p[i]); } printf("\n"); /* διέλευση (εκτύπωση) πίνακα ακεραίων */ int *p,a[N]; for (p=a; p<a+N; p++) { printf("%d ",*p); } printf("\n"); Προγραμματισμός Ι lalis@inf.uth.gr
Πίνακες από δείκτες Οι πίνακες από δείκτες (π.χ. *b[Ν]) «μοιάζουν» με 2-διάστατους πίνακες (π.χ. a[Ν][Μ]), όμως: Κάθε σειρά a[i] του 2-διάστατου πίνακα a έχει ακριβώς τον ίδιο αριθμό στοιχείων (Μ). Οι σειρές του πίνακα a αποθηκεύονται πάντα σε συνεχόμενες θέσεις μνήμης, η μία μετά την άλλη. Κάθε δείκτης b[i] του πίνακα b μπορεί να δείχνει σε εντελώς διαφορετική περιοχή μνήμης, η οποία να μην έχει καμία σχέση με τις περιοχές μνήμης όπου δείχνουν οι υπόλοιποι δείκτες του πίνακα b. Τα δεδομένα που βρίσκονται αποθηκευμένα εκεί όπου δείχνουν τα στοιχεία του b, μπορεί να «ανήκουν» σε συμβατικές μεταβλητές του προγράμματος. Προγραμματισμός Ι lalis@inf.uth.gr
2-διάστατος πίνακας αντικειμένων τύπου Τ πίνακας από δείκτες σε αντικείμενα τύπου Τ T a[N][M]; T *b[N]; a b N … … … N … … … … … … NULL … M … δεδομένα τύπου Τ Προγραμματισμός Ι lalis@inf.uth.gr
Παράμετροι της main Συχνά είναι βολικό το πρόγραμμα να δέχεται κάποια δεδομένα ως παράμετρους εκκίνησης αντί να τα ζητά από τον χρήστη μέσω αντίστοιχου διαλόγου. Η συνάρτηση main δέχεται δύο παραμέτρους. 1. Τον αριθμό τον ορισμάτων argc (argument count) που περάστηκαν στο πρόγραμμα από το περιβάλλον εκτέλεσης, συμπεριλαμβανομένου του ονόματος του. 2. Τον πίνακα από δείκτες-σε-χαρακτήρα argv (argument vector), όπου το i-οστό στοιχείο του πίνακα περιέχει ένα δείκτη σε θέση μνήμης όπου βρίσκεται αποθηκευμένο το i-οστό αλαφαριθμητικό που δόθηκε ως όρισμα από την γραμμή εντολών. Προγραμματισμός Ι lalis@inf.uth.gr
>./myprog one 2 three 45 0x06 qkja<enter> int main (int argc, char *argv[]) { … } 7 o n e \0 4 5 \0 t h r e e \0 2 \0 x 6 \0 m y p r o g \0 q k j a \0 Προγραμματισμός Ι lalis@inf.uth.gr
/* εκτυπώνει τα ορίσματα εκκίνησης */ #include <stdio.h> int main(int argc, char *argv[]) { int i; for (i=0; i<argc; i++) { printf("%s ", argv[i]); } printf("\n"); >./myprog one 2 three 45 0x06 qkja<enter> myprog one 2 three 45 0x06 qkja > Προγραμματισμός Ι lalis@inf.uth.gr
/* ταξινόμηση αλφαριθμητικών με ευρετήριο */ #include <stdio.h> #include <string.h> #define N 7 #define MAXNAMELEN 7 int main(int argc, char *argv[]) { char names[Ν][MAXNAMELEN],*idx[N],*tmp; int i,j; for (i=0; i<N; i++) { printf("enter name: "); scanf("%6s", names[i]); } for (i=0; i<N; i++) { idx[i] = names[i]; } for (j=i; j<N; j++) { if (strcmp(idx[i],idx[j])>0) { tmp = idx[i]; idx[i] = idx[j]; idx[j] = tmp; for(i=0; i<N; i++) { printf("%s\n", idx[i]); } συνάρτηση σύγκρισης αλφαριθμητικών Προγραμματισμός Ι lalis@inf.uth.gr
πριν την ταξινόμηση του ευρετηρίου πίνακας από N δείκτες σε ονόματα στον πίνακα Πίνακας από 7 ονόματα (το πολύ 6 χαρακτήρων) char *idx[7]; char names[7][7]; d o n a l d k a t h y ? j o h n ? ? m a r i n a a l e x ? ? k o s t a s m a r y ? ? Προγραμματισμός Ι lalis@inf.uth.gr
μετά την ταξινόμηση του ευρετηρίου πίνακας από N δείκτες σε ονόματα στον πίνακα Πίνακας από 7 ονόματα (το πολύ 6 χαρακτήρων) char *idx[7]; char names[7][7]; d o n a l d k a t h y ? j o h n ? ? m a r i n a a l e x ? ? k o s t a s m a r y ? ? Προγραμματισμός Ι lalis@inf.uth.gr