Δημοσιεύτηκε: 03 Σεπ 2011, 12:01
Επιστρέφοντας στα strings, ο ορισμός:
βασικά ορίζει έναν πίνακα από 100 χαρακτήρες, αυτό δεν είναι εξ' ορισμού string! Τα strings πρέπει να σηματοδοτούν το τρέχον μήκος τους με έναν μηδενικό χαρακτήρα, και ο συγκεκριμένος ορισμός δεν μας εξασφαλίζει κάτι τέτοιο (βασικά μας το εξασφαλίζει ΜΟΝΑΧΑ αν το s το ορίζουμε ως καθολική μεταβλητή... περισσότερα παρακάτω).
Αντίθετα, αρχικοποιώντας ως string τον παραπάνω πίνακα όταν τον ορίζουμε...
τότε ο 8ος χαρακτήρας του είναι εγγυημένα ο '\0', γιατί λόγω της συγκεκριμένης αρχικοποίησης τον προσθέτει αυτόματα ο compiler. Και μάλιστα το συγκεκριμένο string έχει χώρο για 100 συνολικά χαρακτήρες (δηλαδή μέγιστο μήκος ή το μέγεθος του αν προτιμάται είναι ίσο με 100 bytes). Και άρα μπορούμε με ασφάλεια να χαρακτηρίσουμε τον παραπάνω πίνακα χαρακτήρων ως string.
Ομοίως κι εδώ...
Ο παραπάνω τρόπος αρχικοποιήσης είναι ΕΙΔΙΚΗ ΠΕΡΙΠΤΩΣΗ ΑΡΧΙΚΟΠΟΙΗΣΗΣ στη C και λειτουργεί μονάχα για πίνακες χαρακτήρων, ως ένδειξη πως η πρόθεσή μας είναι να τους διαχειριστούμε ως strings!
Ο στάνταρ τρόπος αρχικοποίησης πινάκων στη C είναι οι τιμές των στοιχείων διαχωρισμένες με κόμματα (πλην του τελευταίου} και όλο μαζί μέσα σε άγκιστρα.
Αν λοιπόν αρχικοποιούσαμε το s με τον στάνταρ τρόπο, δηλαδή...
τότε κανονικά δεν μπορούμε να μιλήσουμε για string, γιατί δεν έχουμε βάλει τον '\0' στο τέλος, οπότε λογικά έχουμε έναν απλό πίνακα χαρακτήρων. Στην πράξη όμως το παραπάνω συμπεριφέρεται ως string λόγω μιας άλλης γενικής ιδιότητας της γλώσσας ως προς τους πίνακες, η οποία στην προκειμένη περίπτωση τυγχάνει να λειτουργεί ας το πούμε ευεργετικά για μας.
Η ιδιότητα αυτή είναι πως σε οποιονδήποτε πίνακα, αν αρχικοποιήσουμε στον ορισμό του λιγότερα στοιχεία από το μέγιστο πλήθος στοιχείων που του έχουμε ορίσει, τότε τα υπόλοιπα αρχικοποιούνται αυτόματα με την τιμή 0. Αντίθετα, αν δεν αρχικοποιήσουμε κανένα στοιχείο, τότε ο πίνακας έχει undefined τιμές στα στοιχεία του (εκτός αν είναι δηλωμένος ως καθολική μεταβλητή, οπότε σε αυτή την περίπτωση αρχικοποιείται αυτόματα με όλα τα στοιχεία του ίσα με 0 χωρίς να χρειάζεται το κάνουμε εμείς).
Παράδειγμα με πίνακα από int, για να το καταλάβουμε:
Παράδειγμα 1ο:
Παράδειγμα 2ο:
Παράδειγμα 3ο:
Παράδειγμα 4ο:
Παράδειγμα 5ο:
Παράδειγμα 6ο:
Οπότε, γνωρίζοντας τα παραπάνω, καταλαβαίνουμε πια πως το...
συμπεριφέρεται σαν κανονικό string επειδή όλοι οι χαρακτήρες από τον 'g' και μετά αρχικοποιούνται αυτόματα με μηδενικές τιμές (και όπως έχουμε πει, οι μηδενικές τιμές στους χαρακτήρες είναι '\0' ).
Δείτε όμως αυτό εδώ:
εδώ πλέον ΔΕΝ έχουμε string, διότι αρχικοποιήσαμε ΟΛΑ τα στοιχεία του s και ΔΕΝ υπάρχει μηδενικός χαρακτήρας! Εδώ έχουμε έναν απλό πίνακα χαρακτήρων, κι αν επιχειρήσουμε να τον διαχειριστούμε σαν string, θα έχουμε κρασαρίσματα διότι η συντριπτική πλειοψηφία των στάνταρ συναρτήσεων διαχείρισης strings στη C θεωρούν δεδομένο πως υπάρχει ο μηδενικός χαρακτήρας και σηματοδοτεί το τρέχον μήκος!
ΗΘΙΚΟ ΔΙΔΑΓΜΑ:
--------------------
όταν η πρόθεση μας είναι να χρησιμοποιήσουμε έναν πίνακα χαρακτήρων ως string τον ορίζουμε και τον αρχικοποιούμε με τον ΕΙΔΙΚΟ ΤΡΟΠΟ που μας παρέχει η γλώσσα για αυτό τον σκοπό ( π.χ. "abcd") ώστε να υπάρχει εγγυημένα μηδενικός χαρακτήρας (τον βάζει αυτόματα ο compiler) είτε ο πίνακας είναι καθολική μεταβλητή είτε τοπική.
Επειδή όμως όλες οι κανόνες έχουν εξαιρέσεις, δείτε αυτό...
εδώ έχουμε ΠΡΟΒΛΗΜΑ!
Αντί ο compiler να μας βγάλει σφάλμα, επειδή δεν του έχουμε αφήσει χώρο να κολλήσει αυτόματα τον μηδενικό χαρακτήρα στο τέλος του s, το θεωρεί ως απλό πίνακα χαρακτήρων, ισοδύναμο δηλαδή με το αμέσως προηγούμενο παράδειγμα. Το μετατρέπει αν προτιμάτε σε ...
Άφησα για το τέλος, την επίσης ειδική περίπτωση:
για να βεβαιωθώ πρώτα πως είμαστε οκ με τα προηγούμενα, που βασίζονται σε λογική πινάκων. Ενώ αυτό εδώ βασίζεται σε λογική δεικτών και πιστεύω είναι καλύτερα να το δούμε ξεχωριστά, αφού καταλάβουμε πρώτα τα περί πινάκων και strings.
- Κώδικας: Επιλογή όλων
char s[100];
βασικά ορίζει έναν πίνακα από 100 χαρακτήρες, αυτό δεν είναι εξ' ορισμού string! Τα strings πρέπει να σηματοδοτούν το τρέχον μήκος τους με έναν μηδενικό χαρακτήρα, και ο συγκεκριμένος ορισμός δεν μας εξασφαλίζει κάτι τέτοιο (βασικά μας το εξασφαλίζει ΜΟΝΑΧΑ αν το s το ορίζουμε ως καθολική μεταβλητή... περισσότερα παρακάτω).
Αντίθετα, αρχικοποιώντας ως string τον παραπάνω πίνακα όταν τον ορίζουμε...
- Κώδικας: Επιλογή όλων
char s[100] = "testing";
τότε ο 8ος χαρακτήρας του είναι εγγυημένα ο '\0', γιατί λόγω της συγκεκριμένης αρχικοποίησης τον προσθέτει αυτόματα ο compiler. Και μάλιστα το συγκεκριμένο string έχει χώρο για 100 συνολικά χαρακτήρες (δηλαδή μέγιστο μήκος ή το μέγεθος του αν προτιμάται είναι ίσο με 100 bytes). Και άρα μπορούμε με ασφάλεια να χαρακτηρίσουμε τον παραπάνω πίνακα χαρακτήρων ως string.
Ομοίως κι εδώ...
- Κώδικας: Επιλογή όλων
char s[] = "testing";
Ο παραπάνω τρόπος αρχικοποιήσης είναι ΕΙΔΙΚΗ ΠΕΡΙΠΤΩΣΗ ΑΡΧΙΚΟΠΟΙΗΣΗΣ στη C και λειτουργεί μονάχα για πίνακες χαρακτήρων, ως ένδειξη πως η πρόθεσή μας είναι να τους διαχειριστούμε ως strings!
Ο στάνταρ τρόπος αρχικοποίησης πινάκων στη C είναι οι τιμές των στοιχείων διαχωρισμένες με κόμματα (πλην του τελευταίου} και όλο μαζί μέσα σε άγκιστρα.
Αν λοιπόν αρχικοποιούσαμε το s με τον στάνταρ τρόπο, δηλαδή...
- Κώδικας: Επιλογή όλων
char s[100] = { 't', 'e', 's', 't', 'i', 'n', 'g' };
τότε κανονικά δεν μπορούμε να μιλήσουμε για string, γιατί δεν έχουμε βάλει τον '\0' στο τέλος, οπότε λογικά έχουμε έναν απλό πίνακα χαρακτήρων. Στην πράξη όμως το παραπάνω συμπεριφέρεται ως string λόγω μιας άλλης γενικής ιδιότητας της γλώσσας ως προς τους πίνακες, η οποία στην προκειμένη περίπτωση τυγχάνει να λειτουργεί ας το πούμε ευεργετικά για μας.
Η ιδιότητα αυτή είναι πως σε οποιονδήποτε πίνακα, αν αρχικοποιήσουμε στον ορισμό του λιγότερα στοιχεία από το μέγιστο πλήθος στοιχείων που του έχουμε ορίσει, τότε τα υπόλοιπα αρχικοποιούνται αυτόματα με την τιμή 0. Αντίθετα, αν δεν αρχικοποιήσουμε κανένα στοιχείο, τότε ο πίνακας έχει undefined τιμές στα στοιχεία του (εκτός αν είναι δηλωμένος ως καθολική μεταβλητή, οπότε σε αυτή την περίπτωση αρχικοποιείται αυτόματα με όλα τα στοιχεία του ίσα με 0 χωρίς να χρειάζεται το κάνουμε εμείς).
Παράδειγμα με πίνακα από int, για να το καταλάβουμε:
Παράδειγμα 1ο:
- Κώδικας: Επιλογή όλων
int numbers[100];
int main( void) {
...
}
Παράδειγμα 2ο:
- Κώδικας: Επιλογή όλων
int main( void) {
int numbers[100];
...
}
Παράδειγμα 3ο:
- Κώδικας: Επιλογή όλων
int main( void) {
int numbers[100] = { 0 };
...
}
Παράδειγμα 4ο:
- Κώδικας: Επιλογή όλων
int main( void) {
int numbers[100] = { 5, 5 };
...
}
Παράδειγμα 5ο:
- Κώδικας: Επιλογή όλων
int main( void) {
int numbers[100] = { 3, 10, 7 };
...
}
Παράδειγμα 6ο:
- Κώδικας: Επιλογή όλων
int main( void) {
int numbers[2] = { 3, 10, 7 };
...
}
Οπότε, γνωρίζοντας τα παραπάνω, καταλαβαίνουμε πια πως το...
- Κώδικας: Επιλογή όλων
char s[100] = { 't', 'e', 's', 't', 'i', 'n', 'g' };
συμπεριφέρεται σαν κανονικό string επειδή όλοι οι χαρακτήρες από τον 'g' και μετά αρχικοποιούνται αυτόματα με μηδενικές τιμές (και όπως έχουμε πει, οι μηδενικές τιμές στους χαρακτήρες είναι '\0' ).
Δείτε όμως αυτό εδώ:
- Κώδικας: Επιλογή όλων
char s[7] = { 't', 'e', 's', 't', 'i', 'n', 'g' };
εδώ πλέον ΔΕΝ έχουμε string, διότι αρχικοποιήσαμε ΟΛΑ τα στοιχεία του s και ΔΕΝ υπάρχει μηδενικός χαρακτήρας! Εδώ έχουμε έναν απλό πίνακα χαρακτήρων, κι αν επιχειρήσουμε να τον διαχειριστούμε σαν string, θα έχουμε κρασαρίσματα διότι η συντριπτική πλειοψηφία των στάνταρ συναρτήσεων διαχείρισης strings στη C θεωρούν δεδομένο πως υπάρχει ο μηδενικός χαρακτήρας και σηματοδοτεί το τρέχον μήκος!
ΗΘΙΚΟ ΔΙΔΑΓΜΑ:
--------------------
όταν η πρόθεση μας είναι να χρησιμοποιήσουμε έναν πίνακα χαρακτήρων ως string τον ορίζουμε και τον αρχικοποιούμε με τον ΕΙΔΙΚΟ ΤΡΟΠΟ που μας παρέχει η γλώσσα για αυτό τον σκοπό ( π.χ. "abcd") ώστε να υπάρχει εγγυημένα μηδενικός χαρακτήρας (τον βάζει αυτόματα ο compiler) είτε ο πίνακας είναι καθολική μεταβλητή είτε τοπική.
Επειδή όμως όλες οι κανόνες έχουν εξαιρέσεις, δείτε αυτό...
- Κώδικας: Επιλογή όλων
char s[7] = "testing";
εδώ έχουμε ΠΡΟΒΛΗΜΑ!
Αντί ο compiler να μας βγάλει σφάλμα, επειδή δεν του έχουμε αφήσει χώρο να κολλήσει αυτόματα τον μηδενικό χαρακτήρα στο τέλος του s, το θεωρεί ως απλό πίνακα χαρακτήρων, ισοδύναμο δηλαδή με το αμέσως προηγούμενο παράδειγμα. Το μετατρέπει αν προτιμάτε σε ...
- Κώδικας: Επιλογή όλων
char s[7] = { 't', 'e', 's', 't', 'i', 'n', 'g' };
Άφησα για το τέλος, την επίσης ειδική περίπτωση:
- Κώδικας: Επιλογή όλων
char *s = "testing";
για να βεβαιωθώ πρώτα πως είμαστε οκ με τα προηγούμενα, που βασίζονται σε λογική πινάκων. Ενώ αυτό εδώ βασίζεται σε λογική δεικτών και πιστεύω είναι καλύτερα να το δούμε ξεχωριστά, αφού καταλάβουμε πρώτα τα περί πινάκων και strings.