Εργαστήριο Τεχνολογίας Λογισμικού
+1 vote
337 views

Έγραψα αυτόν τον πολύ απλό κώδικα. Ωστόσο, όταν εισάγω μία συμβολοσειρά που περιέχει τουλάχιστον ένα κενό, στην έξοδο εμφανίζονται μόνο οι χαρακτήρες μέχρι το κενό. Κάνω κάτι λάθος, ή δεν γίνεται να εισάγουμε συμβολοσειρά με κενά με την scanf;

in progintro by (550 points) | 337 views
+2

Μέχρι να έρθει μια εμπεριστατωμένη απάντηση αφήνω εδώ το man page του scanf. Ψάξε για το conversion s.

2 Answers

+2 votes
Best answer

Η συνάρτηση scanf με το όρισμα %s, διαβάζει μέχρι να βρει whitespace, όπως μπορείς να δεις και εδώ.

Έτσι, ανάλογα με το input που περιμένεις να σου δώσει ο χρήστης σου, μπορείς να φτιάξεις και το πρόγραμμα σου.

by (2.2k points)
selected by
+1

Εναλλακτικά μπορεί να χρησιμοποιηθεί η gets (ή η fgets καλύτερα που είναι και safe), αν θες να διαβάζεις το input αναλλοίωτο.

+2 votes

Να πω και 2 λόγια επιπλέον. Έχεις κάποια "λαθάκια" τα οποία δεν έχεις καταλάβει ότι έχεις κάνει. Και θα προσπαθήσω να τα εξηγήσω όσο πιο απλά γίνεται. :))) Αν δεν έχετε κάνει pointers ακομή, έλα πάλι στην απάντηση αυτή όταν κάνετε, θα το κατανοήσεις πιο εύκολα. Παρόλαυτα κάνε μια προσπάθεια να μείνεις μαζί μου.

char a[30];
scanf("%s", &a);

Εδώ έχεις δώσει στην scanf τη διεύθυνση του a. Όμως το a είναι πίνακας και αποτελεί λοιπόν από μόνος του διεύθυνση(περίπου). Άρα, εσύ λες στη scanf να γράψει στην διεύθυνση που βρίσκεται η διεύθυνση του πίνακα a. Στη συγκεκριμένη περίπτωση δεν βλέπεις λάθος για δύο λόγους. Ο πρώτος είναι ότι εδώ αυτά τα δύο κάπως ταυτίζονται μιας και το a είναι σύμβολο και όχι διεύθυνση και επιπλέον έχεις γράψει αυτό:

printf("%d", &a);

Όπου πάλι έχεις δώσει στην printf την διεύθυνση που βρίσκεται η διεύθυνση του πίνακα a. Είπαμε όμως εδώ τα δύο αυτά είναι ίδια.

Αν όμως είχες αυτό;

char *pointer;
char a[30];
pointer = a;
scanf("%s", &pointer);

Τότε, ενώ στην αρχή ο pointer δείχνει εκεί που βρίσκεται ο πίνακας σου, δηλαδή, έχουμε κάτι τέτοιο:

pointer ---->   |         a[0]              |        
                |         a[1]              |
                |         a[2]              |

Mόλις πραγματοποιηθεί το scanf η διεύθυνση του pointer σου θα είναι τα δεδομένα εισόδου που έδωσες μέσω της scanf, και ουσιαστικά θα δειχνεί πια σε κάτι άλλο, σε μια διεύθυνση που απαρτίζεται από τα δεδομένα που έγραψες. Σίγουρα πάντως όχι στον πίνακα a.

Ομοίως αν κάνεις αυτό σε c++ (το οποίο αργότερα στη σχολή θα το χρησιμοποιείς συχνά και λέγεται δυναμικός πίνακας γιατί έχουμε δυναμική παραχώρηση μνήμης).

char *foo;
foo = new char[30];
scanf("%s", &foo);

Όλα αυτά, λοιπόν, είναι λάθος, αν δεν τα καταλαβαίνεις τώρα, θα τα καταλάβεις αργότερα, θεώρησα οκ να σου δώσω κάποια ερεθίσματα. Αν θες τα κρατάς και ψάχνεσαι παραπάνω, αλλιώς πέτα τα και προχώρα για μια ήσυχη και τέλεια ζωή.

Το σωστό είναι αυτό:

char a[30];
scanf("%29s", a);
printf("%s", a);

Ααα και η scanf δεν ενδείκνυται για διάβασμα συμβολοσειρών. Γιατί δεν τσεκάρει το πλήθος των χαρακτήρων που διαβάζονται εκτός αν κάνεις αυτό που έκανα παραπάνω:

scanf("%29s", a);

Ώστε να μπορεί να διαβάσει το πολύ 29 χαρακτήρες και ο τελευταίος να είναι το '\0' που βάζει από μόνη της.

Όπως και να χει, η fgets() είναι καλύτερη λύση γενικά. Ψάξε γι' αυτήν εδώ.

Πολύ πιθανόν να μην κατάλαβες τίποτα, γιατί είναι νωρίς ακόμη. Κράτα τι είναι σωστό για αρχή, και έλα πάλι εδώ όταν γνωρίζεις περισσότερα.

by (470 points)

301 questions

289 answers

288 comments

909 users