nek1313 Δημοσ. 13 Νοεμβρίου 2018 Share Δημοσ. 13 Νοεμβρίου 2018 (επεξεργασμένο) γεια σας , σημερα εγραφα στη σχολη μια προοδο και στο πρωτο θεμα ζητουσε να γραψουμε ενα προγραμμα σε C που να εκτυπωνει στο τερματικο το μεγαλυτερο σε μηκος ορισμα της main() αλλα να το εμφανιζει με μετατροπη των μικρων γραμματων του σε κεφαλαια . Αν υπαρχουν περισσοτερα απο ενα ορισματα με το ιδιο μεγιστο μηκος , να εκτυπωνει το πρωτο . Εγω εκανα αυτο : #include <stdio.h> #include <stdlib.h> #include <ctype.h> #include <string.h> int main(int argc , char *argv[]) { int i ; int y = 0 ; char s[y] ; int j = 0 ; for (i = 1 ; i < argc ; i++) { if (strlen(argv[i]) > y) { y = i ; } } strcpy(s,argv[y]); while (s[j]) { s[j] = toupper(s[j]); j ++; } printf("%s \n" , s) ; return (0); } το οποιο περναει απο τον compiler , δεν βγαζει λαθη κατα την εκτελεση αν τα ορισματα εχουν ενα κανονικο μηκος (κατω απο 20 χαρακτηρες), ομως βγαζει σε αρκετες περιπτωσεις λαθος αποτελεσμα . Πιστευω οτι εχω κανει καποιο λογικο λαθος στο κωδικα , το οποιο δεν μπορω να ανιχνευσω μεχρι τώρα. Ολες οι ιδεες σας ειναι φυσικα ευπροσδεκτες . Για να βγαλει σωστο αποτελεσμα , εχω παρατηρησει οτι τα μηκη των ορισματων πρεπει να ακολουθουν ενα μοτιβο οπως τα διαβαζεις απο το πρωτο προς το τελευταιο . Επεξ/σία 13 Νοεμβρίου 2018 από nek1313 Συνδέστε για να σχολιάσετε Κοινοποίηση σε άλλες σελίδες άλλες επιλογές
kaliakman Δημοσ. 14 Νοεμβρίου 2018 Share Δημοσ. 14 Νοεμβρίου 2018 Το πρόβλημα είναι όταν γράφεις char s[y]; Δεν κάνει αυτό που θέλεις. Η πιο εύκολη λύση που μπορείς να κάνεις είναι να καλείς toupper(argv[y]) για όλο το μέγεθος του argv[y] όπου το argv[y] το μεγαλύτερο ορισμα. Συνδέστε για να σχολιάσετε Κοινοποίηση σε άλλες σελίδες άλλες επιλογές
nek1313 Δημοσ. 14 Νοεμβρίου 2018 Μέλος Share Δημοσ. 14 Νοεμβρίου 2018 δε νομιζω να φταιει αυτο που λες , γιατι και αυτος ο κωδικας (χωρις το char s[y] ) που εκτυπωνει απλα το μεγαλυτερο σε μηκος ορισμα φαινεται να εχει προβλημα , γιατι δε τρεχει σωστά . #include <stdio.h> #include <stdlib.h> #include <ctype.h> #include <string.h> int main(int argc , char *argv[]) { int i ; int y = 0 ; for (i = 1 ; i < argc ; i++) { if (strlen(argv[i]) > y) { y = i ; } } printf("%s \n" , argv[y]) ; return 0; } Συνδέστε για να σχολιάσετε Κοινοποίηση σε άλλες σελίδες άλλες επιλογές
kaliakman Δημοσ. 14 Νοεμβρίου 2018 Share Δημοσ. 14 Νοεμβρίου 2018 (επεξεργασμένο) 16 λεπτά πριν, nek1313 είπε δε νομιζω να φταιει αυτο που λες , γιατι και αυτος ο κωδικας (χωρις το char s[y] ) που εκτυπωνει απλα το μεγαλυτερο σε μηκος ορισμα φαινεται να εχει προβλημα , γιατι δε τρεχει σωστά . #include <stdio.h> #include <stdlib.h> #include <ctype.h> #include <string.h> int main(int argc , char *argv[]) { int i ; int y = 0 ; for (i = 1 ; i < argc ; i++) { if (strlen(argv[i]) > y) { y = i ; } } printf("%s \n" , argv[y]) ; return 0; } Πριν ήμουν από κινητό και το είδα γρήγορα αλλά αυτό που σου είπα ήταν λάθος έτσι και αλλιώς. Το λάθος σου είναι ότι συγκρίνεις το strlen(..) με το y αλλά το y δεν είναι το μεγαλύτερο μήκος αλλά ένα index. Το ότι σου δούλευε πριν είναι επειδή έτυχε. Θες μια μεταβλητή για το index του μεγαλύτερο σε μήκος arg αλλά και μια για το μέγιστο μήκος. Αν εξαρχής είχες βάλει καλύτερα ονόματα μεταβλητών αντί για y θα το είχες δει μόνος σου. Επεξ/σία 14 Νοεμβρίου 2018 από kaliakman 1 Συνδέστε για να σχολιάσετε Κοινοποίηση σε άλλες σελίδες άλλες επιλογές
nek1313 Δημοσ. 14 Νοεμβρίου 2018 Μέλος Share Δημοσ. 14 Νοεμβρίου 2018 σε ευχαριστω , την εβγαλα . #include <stdio.h> #include <stdlib.h> #include <ctype.h> #include <string.h> int main(int argc , char *argv[]) { int i ; int pos_max = 0 ; int max = 0 ; char s[max]; int c = 0 ; for (i = 1 ; i < argc ; i++) { if (strlen(argv[i]) > max) { max = strlen(argv[i]); pos_max = i ; } } strcpy(s,argv[pos_max]); while (s[c]) { s[c] = toupper(s[c]); c ++; } printf("%s \n" , s) ; return 0; } εχεις απολυτο δικαιο σε αυτο με τα ονοματα των μεταβλητων ,στην αρχη το ειχα σκεφτει αλλα μετα το ξεχασα τελειως και χαθηκα στις ετοιμες strlen , strcpy, toupper Συνδέστε για να σχολιάσετε Κοινοποίηση σε άλλες σελίδες άλλες επιλογές
kaliakman Δημοσ. 14 Νοεμβρίου 2018 Share Δημοσ. 14 Νοεμβρίου 2018 3 λεπτά πριν, nek1313 είπε σε ευχαριστω , την εβγαλα . #include <stdio.h> #include <stdlib.h> #include <ctype.h> #include <string.h> int main(int argc , char *argv[]) { int i ; int pos_max = 0 ; int max = 0 ; char s[max]; int c = 0 ; for (i = 1 ; i < argc ; i++) { if (strlen(argv[i]) > max) { max = strlen(argv[i]); pos_max = i ; } } strcpy(s,argv[pos_max]); while (s[c]) { s[c] = toupper(s[c]); c ++; } printf("%s \n" , s) ; return 0; } εχεις απολυτο δικαιο σε αυτο με τα ονοματα των μεταβλητων ,στην αρχη το ειχα σκεφτει αλλα μετα το ξεχασα τελειως και χαθηκα στις ετοιμες strlen , strcpy, toupper Διόρθωσες το πρόβλημα αλλά το πρώτο που σου είπα το άφησες. Το char s[max] που γράφεις δεν ισχύει. Γράφεις ότι θέλεις ένα array με 0 χαρακτήρες. Πάλι κατά τύχη δουλεύει. Είτε δεν θα αντιγραψεις το string σε άλλη μεταβλητή είτε θα πρέπει να κάνεις πρώτα δυναμική δέσμευση μνήμης και μετά αντιγραφή. Συνδέστε για να σχολιάσετε Κοινοποίηση σε άλλες σελίδες άλλες επιλογές
nek1313 Δημοσ. 14 Νοεμβρίου 2018 Μέλος Share Δημοσ. 14 Νοεμβρίου 2018 #include <stdio.h> #include <stdlib.h> #include <ctype.h> #include <string.h> int main(int argc , char *argv[]) { int i ; int pos_max = 0 ; int max = 0 ; int c = 0 ; for (i = 1 ; i < argc ; i++) { if (strlen(argv[i]) > max) { max = strlen(argv[i]); pos_max = i ; } } while (argv[pos_max][c]) { argv[pos_max][c] = toupper(argv[pos_max][c]); c ++; } printf("%s \n" , argv[pos_max]) ; return 0; } μαλλον αυτο προτεινεις , τη malloc καλυτερα να την αποφυγω σε αυτο αφου δεν ειναι αναγκαια . παντως η εξεταση ηταν τρεχει (10)/ δε τρεχει(0) , οποτε αν εγραφα το παραπανω με strcpy (βγαζει οσες φορες δοκιμασα σωστο αποτελεσμα) 10 θα μου εβαζε ! για καποιο λογο η C το καταλαβαινει το char s[max] και το αρχικοποιει με max = τη τιμη που βγηκε απο το loop πριν το χρησιμοποιησει ... Συνδέστε για να σχολιάσετε Κοινοποίηση σε άλλες σελίδες άλλες επιλογές
kaliakman Δημοσ. 14 Νοεμβρίου 2018 Share Δημοσ. 14 Νοεμβρίου 2018 (επεξεργασμένο) 33 λεπτά πριν, nek1313 είπε #include <stdio.h> #include <stdlib.h> #include <ctype.h> #include <string.h> int main(int argc , char *argv[]) { int i ; int pos_max = 0 ; int max = 0 ; int c = 0 ; for (i = 1 ; i < argc ; i++) { if (strlen(argv[i]) > max) { max = strlen(argv[i]); pos_max = i ; } } while (argv[pos_max][c]) { argv[pos_max][c] = toupper(argv[pos_max][c]); c ++; } printf("%s \n" , argv[pos_max]) ; return 0; } μαλλον αυτο προτεινεις , τη malloc καλυτερα να την αποφυγω σε αυτο αφου δεν ειναι αναγκαια . παντως η εξεταση ηταν τρεχει (10)/ δε τρεχει(0) , οποτε αν εγραφα το παραπανω με strcpy (βγαζει οσες φορες δοκιμασα σωστο αποτελεσμα) 10 θα μου εβαζε ! για καποιο λογο η C το καταλαβαινει το char s[max] και το αρχικοποιει με max = τη τιμη που βγηκε απο το loop πριν το χρησιμοποιησει ... Ναι αυτή είναι σωστή λύση. Τώρα, αυτό που λες δεν παίζει σαν σενάριο. Είσαι απλά τυχερός και δεν σκάει. Αν το δοκιμάσεις σε άλλο μηχάνημα ή αύριο μπορεί να σκάει συνέχεια. Αν σε πέρναγε δεν θα είχε κοιτάξει τι κάνεις. Εγώ πάντως αν το νόημα της προόδου είναι αν ξέρετε c πιθανότατα δεν θα σε πέρναγα. Γνώμη μου πάντα, μην παρεξηγηθω. Επεξ/σία 14 Νοεμβρίου 2018 από kaliakman 1 Συνδέστε για να σχολιάσετε Κοινοποίηση σε άλλες σελίδες άλλες επιλογές
Lanike71 Δημοσ. 14 Νοεμβρίου 2018 Share Δημοσ. 14 Νοεμβρίου 2018 Η λογική των καθηγητών, μιας και το ανέφερες, είναι "αν τρέχει, την κοιτάω παρακάτω να δω τι κάνει. Αν δεν τρέχει , δεν την κοιτάω καν" και όχι αυτό που λες, δηλαδή τρέχει =10. Συνδέστε για να σχολιάσετε Κοινοποίηση σε άλλες σελίδες άλλες επιλογές
nek1313 Δημοσ. 14 Νοεμβρίου 2018 Μέλος Share Δημοσ. 14 Νοεμβρίου 2018 (επεξεργασμένο) @kaliakman Πιστευω οτι δε σκαει σε κανενα μηχανημα το συγκεκριμενο , και το ξερω οτι δεν ειμαι και καλος στη C . @Lanike71 o συγκεκριμενος καθηγητης μας το ειχε δηλωσει ξεκαθαρα και το εγραφε και πανω στα θεματα , στο πρωτο θεμα που επιανε 5/10 δε κοιταει καθολου το κωδικα , τρεχει αυτοματα μαλλον με ενα σκριπτακι τα 200+ πρωτα θεματα ολων των φοιτητων και οσα βγαζουν το σωστο αποτελεσμα παιρνουν 10 , οσα κατι αλλο η και τιποτα παιρνουν 0 . Δε τον ενδιαφερει το ποσο αποδοτικος , καλογραμμενος η με καλα σχολια ειναι ο κωδικας , τον ενδιαφερει μονο αν κανει αυτο που ζητηθηκε . Στο δευτερο θεμα κοιταει αναλυτικα το κωδικα και δινει καποιες μοναδες ασχετα με τον αν η πως τρεχει . Επεξ/σία 14 Νοεμβρίου 2018 από nek1313 Συνδέστε για να σχολιάσετε Κοινοποίηση σε άλλες σελίδες άλλες επιλογές
imitheos Δημοσ. 14 Νοεμβρίου 2018 Share Δημοσ. 14 Νοεμβρίου 2018 12 ώρες πριν, nek1313 είπε για καποιο λογο η C το καταλαβαινει το char s[max] και το αρχικοποιει με max = τη τιμη που βγηκε απο το loop πριν το χρησιμοποιησει ... Όχι δεν το καταλαβαίνει. Η εκχώρηση μνήμης γίνεται (ή τουλάχιστον έτσι πρέπει) την στιγμή της δήλωσης και όχι τη στιγμή της χρήσης οπότε εκχωρείς 0 bytes μνήμης. 11 ώρες πριν, kaliakman είπε Ναι αυτή είναι σωστή λύση. Τώρα, αυτό που λες δεν παίζει σαν σενάριο. Είσαι απλά τυχερός και δεν σκάει. Αν το δοκιμάσεις σε άλλο μηχάνημα ή αύριο μπορεί να σκάει συνέχεια. Ούτε αυτό είναι η σωστή λύση. Αφενός πειράζει το όρισμα argv[τάδε]. Αυτό δεν απαγορεύεται φυσικά αλλά έτσι όπως διαβάζω την άσκηση την ερμηνεύω ότι είτε πρέπει να χρησιμοποιηθεί νέα μεταβλητή στην οποία να αντιγραφεί το argv ή να χρησιμοποιηθεί η toupper μέσα στην printf ώστε να εκτυπωθεί κατευθείαν η έξοδος της toupper. Μπορεί φυσικά η ερμηνεία μου να είναι λάθος. Ένα άλλο πρόβλημα είναι ότι δεν ελέγχει το πλήθος των παραμέτρων. Αν το πρόγραμμα εκτελεστεί χωρίς παραμέτρους, τότε το for του ξεκινά από i = 1 μέχρι argc (δηλαδή 0) οπότε ακυρώνεται το for και εκτελείται το επόμενο κομμάτι του κώδικα με το pos_max να έχει την αρχική του τιμή 0 δηλαδή εμφανίζεται με κεφαλαία το όνομα του εκτελέσιμου. Και αυτό επίσης είναι δική μου ερμηνεία της άσκησης αλλά θεωρώ ότι δεν θέλει αυτό η άσκηση. 4 ώρες πριν, nek1313 είπε @kaliakman Πιστευω οτι δε σκαει σε κανενα μηχανημα το συγκεκριμενο , και το ξερω οτι δεν ειμαι και καλος στη C . Γιατί δεν κάνεις ένα τεστ; Δεν χρειάζεται ούτε σε άλλη αρχιτεκτονική να πας, όπως πρότεινε ο kaliakman, ούτε τίποτα. Τρέξε το πρόγραμμά σου με ολοένα μεγαλύτερο όρισμα και δες τι θα κάνει. Τρέξε το με όρισμα Tria, μετά με TriaPoulakia, μετά με TriaPoulakiaKa8ontai και ούτω καθεξής. % gcc -Wall -O0 -o tmp tmp.c % for i in $(seq 1 100); do echo running with argument of $i characters ./tmp $(printf %${i}s | tr " " "a") if [ $? != 0 ]; then echo error break fi done running with argument of 1 characters A running with argument of 2 characters AA ... running with argument of 15 characters AAAAAAAAAAAAAAA running with argument of 16 characters error % clang -O0 -o tmp tmp.c % for i in $(seq 1 100); do echo running with argument of $i characters ./tmp $(printf %${i}s | tr " " "a") if [ $? != 0 ]; then echo error break fi done running with argument of 1 characters A running with argument of 2 characters AA ... running with argument of 8 characters AAAAAAAAP-Nü� running with argument of 9 characters AAAAAAAA '`³ý� running with argument of 10 characters AAAAAAAAÀÔ"Rý� running with argument of 11 characters AAAAAAAAÀ4äAý� running with argument of 12 characters AAAAAAAA`,ñZü� running with argument of 13 characters AAAAAAAA`)P4ý� running with argument of 14 characters AAAAAAAAðTþ� running with argument of 15 characters AAAAAAAAà.ü� running with argument of 16 characters error % dmesg [15682.866007] tmp[5348]: segfault at 7ffe17006161 ip 00000000004012e6 sp 00007ffe177751b0 error 4 in tmp[401000+1000] Το παραπάνω απλό scriptάκι τρέχει τον κώδικά σου δίνοντάς του μία ποσότητα από μικρά άλφα σαν όρισμα. Μεταγλώττισα τον κώδικά σου και με gcc και με clang. Όπως βλέπεις, αρχικά όλα φαίνονται να λειτουργούν καλά και "δεν σκάει" όπως είπες, τουλάχιστον στην αρχή. Γιατί γίνεται αυτό; Γιατί όπως και στις άλλες εκχωρήσεις μνήμης, ο compiler δεν εκχωρεί όσο του ζήτησες (εν προκειμένω 0) αλλά εκχωρεί ό,τι τον βολεύει αυτόν οπότε μπορεί πχ να εκχώρησε 10 bytes και έτσι μέχρι ένα σημείο έχεις μνήμη για να γράψεις και φαίνεται να δουλεύει. Ή μπορεί να εκχωρεί όντως 0 bytes αλλά να υπάρχουν κάποια padding bytes για άλλες μεταβλητές οπότε να γράφεις εκεί και να μην φαίνεται ότι υπάρχει πρόβλημα. Γράφοντας όμως 16 bytes σκάνε και ο gcc και ο clang με τον 2ο να έχει προβλήματα από πολύ πριν και να εμφανίζει σκουπίδια. Σε 32bit μεταγλώττιση και οι δύο κόλλησαν στα 8 bytes. Αν χρησιμοποιήσεις optimizations, τότε παράγεται διαφορετικός κώδικας και μπορεί να κρεμάσει σε άλλο σημείο. Σε εμένα με Ο2 ο gcc κρεμάει στα 45 bytes και ο clang κολλάει κατευθείαν στο 1 byte Με άλλα λόγια, το γεγονός ότι δεν το παρατήρησες να σκάει, δεν σημαίνει ότι δεν σκάει κιόλας. Να είσαι 100% σίγουρος ότι κάποια στιγμή θα σκάσει. 2 Συνδέστε για να σχολιάσετε Κοινοποίηση σε άλλες σελίδες άλλες επιλογές
kaliakman Δημοσ. 14 Νοεμβρίου 2018 Share Δημοσ. 14 Νοεμβρίου 2018 7 λεπτά πριν, imitheos είπε .... Αρχικά και εγώ αν είδες πρότεινα απευθείας το αποτέλεσμα της toupper στο printf αλλά ο TS προτίμησε να αλλάξει το όρισμα. Όσο για το δεύτερο που αναφέρεις οι γνώμες διίστανται μιας και θεωρητικά το πρόγραμμα "είναι" argument. Προφανώς δεν έχει νόημα αυτή η συζήτηση αφού ο ΤS δεν έχει ξεκαθαρίσει αλλά θέματα αλλά να 'χαμε να λέγαμε. Επίσης ενδιαφέρον που με O2 ο gcc δεν σκάει σε δύναμη του 2. Συνδέστε για να σχολιάσετε Κοινοποίηση σε άλλες σελίδες άλλες επιλογές
nek1313 Δημοσ. 14 Νοεμβρίου 2018 Μέλος Share Δημοσ. 14 Νοεμβρίου 2018 @kaliakman οταν λες TS τι εννοεις ; σε μενα αναφερεσαι γιατι δε καταλαβα ... Συνδέστε για να σχολιάσετε Κοινοποίηση σε άλλες σελίδες άλλες επιλογές
kaliakman Δημοσ. 14 Νοεμβρίου 2018 Share Δημοσ. 14 Νοεμβρίου 2018 Μόλις τώρα, nek1313 είπε @kaliakman οταν λες TS τι εννοεις ; σε μενα αναφερεσαι γιατι δε καταλαβα ... ναι σημαίνει Topic Starter Συνδέστε για να σχολιάσετε Κοινοποίηση σε άλλες σελίδες άλλες επιλογές
LukaP Δημοσ. 15 Νοεμβρίου 2021 Share Δημοσ. 15 Νοεμβρίου 2021 Στις 14/11/2018 στις 2:15 ΠΜ, nek1313 είπε #include <stdio.h> #include <stdlib.h> #include <ctype.h> #include <string.h> int main(int argc , char *argv[]) { int i ; int pos_max = 0 ; int max = 0 ; int c = 0 ; for (i = 1 ; i < argc ; i++) { if (strlen(argv[i]) > max) { max = strlen(argv[i]); pos_max = i ; } } while (argv[pos_max][c]) { argv[pos_max][c] = toupper(argv[pos_max][c]); c ++; } printf("%s \n" , argv[pos_max]) ; return 0; } μαλλον αυτο προτεινεις , τη malloc καλυτερα να την αποφυγω σε αυτο αφου δεν ειναι αναγκαια . παντως η εξεταση ηταν τρεχει (10)/ δε τρεχει(0) , οποτε αν εγραφα το παραπανω με strcpy (βγαζει οσες φορες δοκιμασα σωστο αποτελεσμα) 10 θα μου εβαζε ! για καποιο λογο η C το καταλαβαινει το char s[max] και το αρχικοποιει με max = τη τιμη που βγηκε απο το loop πριν το χρησιμοποιησει ... Χαίρετε, παρατηρώ το τελικό κώδικα του αρχικού συντάκτη @nek1313 και τις βελτιώσεις που προτείνατε οι @imitheos & @kaliakman και πιο συγκεκριμένα το να χρησιμοποιήσει μέσα στην printf την toupper για τους ευνόητους λόγους. Πως θα μπορούσε όμως να το κάνει κάποιος αυτό, αφού η toupper είναι μέσα σε βρόχο και όπως επισημάνθηκε χωρίς να χρησιμοποιηθεί κάποια προσωρινή μεταβλητή; Μπορεί η όλη λειτουργικότητα ενός βρόχoυ να μπει μέσα σε ένα printf; Αν ναι, πως ακριβώς γίνεται; Συνδέστε για να σχολιάσετε Κοινοποίηση σε άλλες σελίδες άλλες επιλογές
Προτεινόμενες αναρτήσεις
Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε
Πρέπει να είστε μέλος για να αφήσετε σχόλιο
Δημιουργία λογαριασμού
Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!
Δημιουργία νέου λογαριασμούΣύνδεση
Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.
Συνδεθείτε τώρα