ασκήσεις ακριβείας
Posted by Νεόφυτος Δημητρίου Sun, 06 Apr 2008 13:18:29 EEST
τι μπορεί να μην πάει καλά με τον πιο κάτω κώδικα;
char *x, *y;
// code omitted for clarity
for (x = strrchr(y, '.') - 1; x > y; x--) {
// code omitted for clarity
}
Reader's Comments
η αρχικοποίηση του y και ο έλεγχος αν δεν υπάρχει καθόλου '.' στο y πριν το loop εν μέσα στο code omitted;
Το encoding να είναι UTF-8 και να μην μπορείς με x– να κινηθείς σωστά μέσα στο string (όταν βάζεις μη αγγλικό κείμενο).
Τι μπορεί να μην πάει καλά:
1-βλ. σχόλιο Ελένης
2-βλ. σχόλιο Αυγουστίνου
3-να ξεκινά ή να τελειώνει το y με τελεία (δεν νομίζω να επιτρέπεται αλλά τέλος πάντων)
4-ίσως 2 τελείες συνεχόμενες στο y
5-το x > y δεν είμαι σίγουρος πώς δουλεύει με pointers
6-ο προγραμματιστής που κάθεται και προγραμματίζει σε C
Η απάντηση πρέπει να είναι συγκεκριμένη (είπαμε, ασκήσεις ακριβείας). Λάβε υπόψη ότι έχεις ταλαιπωρηθεί να βρεις που είναι το πρόβλημα στον κώδικα. Χρησιμοποίησες gdb κι έχεις καταλήξει στο υπόψη κομμάτι κώδικα. Πρέπει να εντοπίσεις τι ακριβώς φταίει και να το διορθώσεις. Διαφορετικά, δεν έχει λογαριασμούς email για τα μέλη του phigita.net.
Μα δεν ανάφερες πουθενά ποιο είναι το σύμπτωμα :P
Ήταν να πω segmentation fault αλλά δεν θα ήταν ακριβής η περιγραφή λόγω του κώδικα που λείπει. Το segmentation fault, ωστόσο, προκύπτει εξαιτίας του τι δεν πάει καλά στον κώδικα που δημοσιεύω.
Σε περιπτωση που δεν υπάρχει '.' στο y τότε αυτό: strrchr(y, '.') επιστρέφει NULL.
και έχουμε το εξής περίεργο:
This is y:eg30
1. x=-1
2. y=6685040
3. x > y =1 // το περίεργο
4. (1==1)=1
Υποθέτω ότι αρνητική τιμή σε pointer δεν έχει νόημα άρα εάν ένας pointer έχει αρνητική τιμή τότε η C … συγχύζεται :P.
Άρα, η συνθήκη του for είναι αληθής και θα έχεις segmentation fault μέσα στο for εάν προσπαθήσεις να διαβάσεις το *x.
Χωρίς να γνωρίζουμε τι ακολουθεί στα σχόλια επιχειρώ:
Άμα το y περιέχει string χωρίς '.' το loop αδυνατεί να εκτελεστεί γιατί με βάση τον κώδικα σωστής κυκλοφορίας: http://www.cplusplus.com/reference/clibrary/cstring/strrchr.html "If the value is not found, the function returns a null pointer."
Αν και λογικά το loop δεν θα έπρεπε να εκτελεστεί καθόλου, η Dec-C++ ξεκινά από αρνητικό αριθμό για pointer και συνεχίζει ακάθεκτη μειώνοντας το αριθμό (-1 σε -2 π.χ.)
Μιας και δεν νομίζω να είναι το πιο πάνω το πρόβλημα επιχειρώ με τα επόμενα:
Ο κώδικας παραβλέπει το τελευταίο κομμάτι μετά το κόμμα, πχ το "first.last" δεν θα προσπέλασε καθόλου το last
Και τέλος μιας και πρόκειται για άσκηση ακριβείας (ποντάρω σε αυτό να είναι το πρόβλημα!): Ο κώδικας δεν θα προσπελάσει ένα χαρακτήρα από τις "πρώτες ομάδες" (με βάση το ποιο πάνω το "first.second.last" το last δεν θα προσπελαστεί ποτέ) οπότε ανάλογα με την χρήση του x θα παίρναμε μόνο "irst.second" ή "first.secon"
Φυσικά τα πιο πάνω προβλήματα λύνονται προσθέτοντας απλός μια τελεία στην αρχή και μια στο τέλος του αλφαριθμητικού που περιέχονται στο y[]
Η Γεωργία επρόλαβαιν με, παρακαλώ όπως γίνει ban!
Ευχαριστώ!
;)
Σωστά!
Το "περίεργο" είναι ότι ο κώδικας εκτελείται όταν η strrchr επιστρέφει NULL. Σε αυτή την περίπτωση, το x αρχικοποιείται με τη θέση μνήμης 0 (για το NULL) - 1. Αν εξετάσεις την τιμή του x ως ακέραιο τότε φαινομενικά θα έχεις (-1 > 6685040) ενώ στην πραγματικότητα έχεις θέση μνήμης 0xffffffff η οποία είναι όντως μεγαλύτερη του 0x660170 (=6685040). Το πρόβλημα λύνεται μεταφέροντας το -1 από την αρχικοποίηση του x ή μετατρέποντας (casting) σε ακέραιους τα x και y πριν από το σχετικό έλεγχο (int) x > (int) y.
Τώρα να δούμε τι θα πει ο Βλαδίμηρος που έγραψε τον κώδικα (εκείνου του δουλεύει — έχω την εντύπωση ότι του δουλεύει επειδή δεν έχει δοκιμάσει με y χωρίς τελείες, π.χ. localhost).
Γεωργία: το βραβείο σου θα το παραλάβεις στην επόμενη phigito-συνάντηση.
:D. Πρέπει να επισημάνω ότι η Ελένη έκανε την αρχή με το σχόλιό της.