TheOneGandalf Δημοσ. 5 Ιανουαρίου 2012 Δημοσ. 5 Ιανουαρίου 2012 (επεξεργασμένο) Καλησπέρα παίδες! Για άλλη μια φορά θα χρειαστώ τη βοηθειάς σας! Έχω την εξής άσκηση για την C! Προσπαθώ να κάνω το πρώτο ερώτημα αλλά δεν μου δουλεύει σωστά. Υλοιποείστε κώδικα που να δέχεται σαν είσοδο απο το πληκτρολοόγιο ένα κείμενο της Αγγλικής γλώσσας και : (α) καταγράφει για κάθε διαφορετική λέξη του κειμένου το πλήθος των εμφανίσεων της. (β) καταγράφει για κάθε διαφορετική λέξη του κειμένου το πλήθος των διαφορετικών γραμμών στις οποίες εμφαίζεται (γ) εμφανίζει ένα μενού επιλογών στο χρήστη με τρεις δυνατότητες : (1) την ανάγνωση μιας λέξης απο το πληκτρολόγιο και στη συνέχεια την εμφάνιση στην οθόνη του αριθμού εμφανίσεων της στο κείμενο, ( 2 ) την ανάγνωση μίας λέξης απο το πληκτρολόγιο και στη συνέχεια την εμφανίση του πλήθους των διαφορετικών γραμμών στις οποίες εμφανίζεται, (3) την έξοδο απο το πρόγραμμα. ΥΠΟΔΕΙΞΗ : Θα θεωρήσετε ότι το τέλος της εισόδου δίνεται με τον χαρακτήρα EOF και ότι μια λεξη οριζεται ως μια συνεχομενη ακολουθία αλφαβητικών χαρακτήρων και ψηφίων που αρχίζει από αλφαβητικό χαρακτήρα, μέγιστου μήκους 100. Η αναγνώριση μιας λέξης να υλοποιηθεί σαν μία ξεχωριστή συνάρτηση στο προγραμμά σας! Παραθέτω τον κώδικα μου. Το πρόβλημα είναι οτι δεν μου τρέχει σωστά για το 1ο ερώτημα. Δηλαδή μερικές φορές μπορεί να εμφανισεί σωστό πλήθος, αλλές φορές τελείως λάθος, άλλες δεν εμφανίζει καθόλου πλήθος! > #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> // Πρωτότυπα συναρτήσεων void checkword( char *text, char *word ); int main( void ) { char *text, *word; int choice; // Εισαγωγή κειμένου απο το πληκτρολόγιο text = ( char * )malloc( sizeof( char ) ); word = ( char * )malloc( sizeof( char ) ); gets( text ); gets( word ); checkword( text, word ); /*// Menu επιλογών printf( "Kalos irthes\n"); printf( "Exeis 3s epiloges : \n"); printf( "(1) Anagnosi mias leksis apo to pliktrologio kai emfanisi arithmou emfanisewn tis sto keimeno \n" ); printf( "(2) Anagnosi mias leksis apo to pliktrologio kai emfanisi plithous diaforetikon grammwn pou emfanizete \n" ); printf( "(3) Eksodos apo to programa! \n" ); printf( "Epelekse mia apo tis treis \n" ); printf( "Epilogi = " ); scanf( "%d", &choice );*/ while ( choice > 3 || choice < 1 ) { printf( "Eipame mia apo tis treis! \n" ); printf( "Epilogi = " ); scanf( "%d", &choice ); } // Τέλος Menu επιλογών } void checkword( char *text, char *word ) { int wordsize; int i = 0; // Μετρητής για τον πίνακα text int j = 0; // Μετρητής για τον πίνακα word int k = 0; // Μετρητής for int plithos = 0; wordsize = strlen( word ); // Πλήθος χαρακτήρων της λέξης που διάβασε ο χρήστης while( text[ i ] != '\0' ) { if ( word[ 0 ] == text[ i ] ) { plithos = 1; for ( k = i + 1; k < i + wordsize; k++ ) { if ( word[ plithos ] == text[ k ] ) { plithos++; } } if ( plithos == wordsize ) { /* * Αφου βρούμε την ζητούμενη λέξη ελέγχουμε αν στην * προηγούμενη και στην επόμενη θέση υπάρχει κενό */ if ( i == 0 ) { if ( isspace( text[ i + wordsize ] ) ) { printf( "Vrika tin leksi sou!\n" ); } } else { if ( isspace( text[ i - 1 ] ) && ( isspace( text[ i + wordsize ] ) || text[ i + wordsize ] != '\0' ) ) { printf( "Vrika tin leksi sou\n" ); } } } } i++; } } Επεξ/σία 6 Ιανουαρίου 2012 από TheOneGandalf
migf1 Δημοσ. 6 Ιανουαρίου 2012 Δημοσ. 6 Ιανουαρίου 2012 Δεν πήγα ακόμα παρακάτω, αλλά αυτό εδώ.. > int main( void ) { char *text, *word; int choice; // Εισαγωγή κειμένου απο το πληκτρολόγιο text = ( char * )malloc( sizeof( char ) ); word = ( char * )malloc( sizeof( char ) ); gets( text ); gets( word ); ... βαράει κάτι seg-faults από δω μέχρι την... Κούλουρη Καταρχήν για τα text και word δεσμεύεις μνήμη για 1 χαρακτήρα στο καθένα τους, κατά 2ον τον αφήνεις uninitialized, κατά 3ον δεν ελέγχεις αν απέτυχαν τα malloc() πριν συνεχίσεις και τέλος χρησιμοποιείς την gets() που είναι depreciated γιατί δεν σε αφήνει να κοντρολάρεις μέχρι πόσους χαρακτήρες θα επιτρέπεις να διαβαστούν στο κάθε string σου.
TheOneGandalf Δημοσ. 6 Ιανουαρίου 2012 Μέλος Δημοσ. 6 Ιανουαρίου 2012 Βασικά έχω κάποιες απορίες, αν μπορείς να μου τις λύσεις. > myArray = ( int * )malloc( 5 * sizeof( int ) ); Έιχα διαβάσει ότι με την παραπάνω εντολή δεσμεύω στην μνήμη χώρο για 5 ints! Kαι ότι στον πίνακα myArray μπορώ να αποθηκεύσω 5 ints. Μια φορά λοιπόν, δοκίμασα να αποθηκεύσω περισσότερους και γινότανε! Δοκίμασα και με αυτήν την εντολή >myArray = ( int * )malloc( sizeof( int ) ); αλλά και με αυτήν το ίδιο. Μπορούσα να αποθηκεύσω πολυ περισσότερους απο 5.. Κάτι τρέχει εδώ... Επίσης, η άσκηση μου λέει ότι 'Θα θεωρήσετε ότι το τέλος της εισόδου δίνεται με τον χαρακτήρα EOF'. Αυτό πως ακριβώς θα το κάνω? Δεν νομίζω να εννοεί ότι στο κείμενο που θα πληκτρολογήσουμε η τελευταία λέξη να είναι η EOF, έτσι δεν είναι? Ακόμα, πως μπορώ να αποθηκεύσω ενα string άγνωστου μεγέθους σε έναν πίνακα? Όταν ας πούμε δεν ξέρουμε εξαρχής πόσο μεγάλο θα είναι το string, δεν μπορούμε να κάνουμε ούτε malloc έτσι δεν είναι? Σε αυτήν την περίπτωση προφανώς χρειάζεται να κάνουμε κάτι άλλο. Καταρχήν για τα text και word δεσμεύεις μνήμη για 1 χαρακτήρα στο καθένα τους, κατά 2ον τον αφήνεις uninitialized, κατά 3ον δεν ελέγχεις αν απέτυχαν τα malloc() πριν συνεχίσεις και τέλος χρησιμοποιείς την gets() που είναι depreciated γιατί δεν σε αφήνει να κοντρολάρεις μέχρι πόσους χαρακτήρες θα επιτρέπεις να διαβαστούν στο κάθε string σου. Τέλος, το 3ο το έπιασα! Πρέπει αφου κάνω malloc να ελέγχω αν επιστρέφει NULL, δηλαδή αν δεν έχει διαθέσιμη μνήμη για να δεσμεύσει. Το 2ο που είπες δεν το έπιασα? Όταν λές αφήνω uninitialized, εννοείς τον δείκτη text? Πρέπει να το αρχικοποιώ σε NULL?
migf1 Δημοσ. 6 Ιανουαρίου 2012 Δημοσ. 6 Ιανουαρίου 2012 Βασικά έχω κάποιες απορίες, αν μπορείς να μου τις λύσεις. > myArray = ( int * )malloc( 5 * sizeof( int ) ); Έιχα διαβάσει ότι με την παραπάνω εντολή δεσμεύω στην μνήμη χώρο για 5 ints! Kαι ότι στον πίνακα myArray μπορώ να αποθηκεύσω 5 ints. Μια φορά λοιπόν, δοκίμασα να αποθηκεύσω περισσότερους και γινότανε! Δοκίμασα και με αυτήν την εντολή >myArray = ( int * )malloc( sizeof( int ) ); αλλά και με αυτήν το ίδιο. Μπορούσα να αποθηκεύσω πολυ περισσότερους απο 5.. Κάτι τρέχει εδώ... Καλημέρα, τα έξτρα αποθηκεύονται ακριβώς μετά από εκεί που τελειώνει η μνήμη που έχεις δεσμεύσει. Ανάλογα με το τι υπήρχε πριν εκεί θα εξαρτηθεί το εάν και πότε θα εμφανιστεί το πρόβλημα. Σίγουρα πάντως υπάρχει πρόβλημα γιατί έχεις αλλάξει ότι υπήρχε πριν σε εκείνην την περιοχή της μνήμης. Επίσης, η άσκηση μου λέει ότι 'Θα θεωρήσετε ότι το τέλος της εισόδου δίνεται με τον χαρακτήρα EOF'. Αυτό πως ακριβώς θα το κάνω? Δεν νομίζω να εννοεί ότι στο κείμενο που θα πληκτρολογήσουμε η τελευταία λέξη να είναι η EOF, έτσι δεν είναι? EOF είναι ένας ειδικός χαρακτήρας, και μέσα στο <stdio.h> υπάρχει ο ορισμός του (συνήθως ορίζεται ως -1). Οπότε απλά σου λέει να βάλεις το EOF ως συνθήκη τερματισμού στο input σου. Συνήθως για να αναπαράξει ο χρήστης τον χαρακτήρα EOF από το πληκτρολόγιο πατάει Ctrl+D ή Ctrl+Z (ανάλογα την πλατφόρμα). Ακόμα, πως μπορώ να αποθηκεύσω ενα string άγνωστου μεγέθους σε έναν πίνακα? Όταν ας πούμε δεν ξέρουμε εξαρχής πόσο μεγάλο θα είναι το string, δεν μπορούμε να κάνουμε ούτε malloc έτσι δεν είναι? Σε αυτήν την περίπτωση προφανώς χρειάζεται να κάνουμε κάτι άλλο. Από την αναθεώρηση C99 και μετά μπορείς να ορίζεις μεταβλητές (άρα και πίνακες) σε οποιαδήποτε γραμμή του κώδικά σου (σε οποιοδήποτε μπλοκ βασικά) οπότε μπορείς π.χ. πρώτα να διαβάζεις από τον χρήστη το μέγεθος σε μια μεταβλητή και κατόπιν να τη χρησιμοποιείς για να φτιάξεις τον πίνακα... > ... size_t maxsize=0U; printf("Enter size for the array: "); scanf("%u", &maxsize); if ( size < 1 ) { /* άκυρο μέγεθος, deal with it */ } int array[ maxsize ] = {0}; ... Πριν από την αναθεώρηση C99 γινόταν με malloc()/calloc() ... > ... int *array = NULL; size_t maxsize=0U; printf("Enter size for the array: "); scanf("%u", &maxsize); if (maxsize > 0) array = calloc(size, sizeof(int) ); if ( !array ) { /* απέτυχε το calloc(), deal with it */ } ... Τέλος, το 3ο το έπιασα! Πρέπει αφου κάνω malloc να ελέγχω αν επιστρέφει NULL, δηλαδή αν δεν έχει διαθέσιμη μνήμη για να δεσμεύσει. Το 2ο που είπες δεν το έπιασα? Όταν λές αφήνω uninitialized, εννοείς τον δείκτη text? Πρέπει να το αρχικοποιώ σε NULL? Ναι, είναι πάντα σοφό τους δείκτες που ορίζεις να τους αρχικοποιείς ΑΜΕΣΑ. Είτε απευθείας με το επιθυμητό malloc()/calloc() ταυτόχρονα με τον ορισμό τους είτε σε NULL. Πέρα από αυτό όμως, αυτό που εννοούσα πριν είναι πως όταν πρόκειται για strings που τα ορίζεις εσύ δυναμικά ως προς το μέγεθός τους, είναι επίσης σοφό να τα αρχικοποιείς με την τιμή '\0' ( που σε ASCII ισοδυναμεί με 0 )σε όλες τις θέσεις τους. Αυτό το κάνεις με 2 τρόπους: α) αντί για malloc() τα φτιάχνεις με calloc() το οποίο μηδενίζει αυτόματα τη μνήμη που δεσμεύει β) τα φτιάχνεις με maloc() αλλά κατόπιν τους γεμίζεις χειροκίνητα με μηδενικά, με την memset()... > /* 1ος τρόπος */ char *text = calloc( 100, sizeof(char) ); /* το calloc() εγγυάται πως η μνήμη που δεσμεύει ξεκινάει με μηδενικές τιμές μέσα της */ /* 2ος τρόπος */ char *text = malloc( 100 * sizeof(char) ); /* το malloc() δεν εγγυάται τα περιεχόμενα της μνήμης που δεσμεύει */ if ( text ) memset( text, '\0', 100 * sizeof(char) ); Οι 2 παραπάνω τρόποι είναι ισοδύναμοι πρακτικά με τους παρακάτω στατικούς ορισμούς του string... > /* 1ος τρόπος */ char text[100]; /* τα αρχικά περιεχόμενα στις 100 θέσεις είναι undefined (μπορούν να περιέχουν οτιδήποτε, δεν ξέρουμε τι) */ /* 2ος τρόπος */ char text[100] = {'\0'}; /* η κάθε μια από τις 100 θέσεις ξεκινάει με περιεχόμενο '\0' */ Το ότι γεμίζουν και οι 100 θέσεις με '\0' στον 2ο τρόπο του στατικού ορισμού συμβαίνει έμμεσα, λόγω της ιδιότητας που έχει η C να γεμίζει με 0 ότι περισσεύει μετά από μερική αρχικοποίηση ενός πίνακα (π.χ. αν ορίζαμε: char *text[100] = { 'h', 'i' }; οι 2 πρώτοι χαρακτήρες θα ήταν οι 2 που βάλαμε στην αρχικοποίηση κι όλοι οι υπόλοιποι αυτόματα θα γίνονταν 0... αν δεν κάναμε καθόλου αρχικοποίηση τότε και οι 100 χαρακτήρες είναι undefined... αυτά ισχύουν για όλους τους πίνακες, όχι μονάχα δηλαδή για πίνακες χαρακτήρων) Σε ότι αφορά τα c-strings, είναι σοφόνα τα ξεκινάς με μηδενικούς χαρακτήρες σε όλες τους τις θέσεις, ως (ανεπαρκές) μέτρο προστασίας σε περίπτωση που ο κώδικάς σου "ξεχάσει" να λάβει υπόψη του πως τα c-strings πρέπει να τελειώνουν σε μηδενικό χαρακτήρα. Θα σε προστατέψει σε ενδεχόμενα λάθη του κώδικά σου που διαχειρίζονται τιμές του string με μήκος μικρότερο του μέγιστου-1 που έχεις ορίσει EDIT: Προστέθηκαν κάποιοι έξτρα έλεγχοι στον κώδικα.
nplatis Δημοσ. 6 Ιανουαρίου 2012 Δημοσ. 6 Ιανουαρίου 2012 Ως προς το μήκος των συμβολοσειρών, αναφέρεται στην εκφώνηση ότι μία λέξη έχει μέγιστο μήκος 100, άρα μπορείς με ασφάλεια να φτιάξεις (όπου χρειαστείς) πίνακες των 101 χαρακτήρων για να τις αποθηκεύσεις.
migf1 Δημοσ. 6 Ιανουαρίου 2012 Δημοσ. 6 Ιανουαρίου 2012 Υπάρχει ασάφεια στην εκφώνηση ως προς την αρχική εισαγωγή του Αγγλικού κειμένου. Αν πρόκειται για κείμενο απροσδιόριστου μέγιστου μήκους, μια συνηθισμένη υλοποίηση είναι η δέσμευση μνήμης ανά τμήματα (chunks) καθώς πληκτρολογεί ο χρήστης, με χρήση της realloc() για κάθε επιμήκυνση.
TheOneGandalf Δημοσ. 6 Ιανουαρίου 2012 Μέλος Δημοσ. 6 Ιανουαρίου 2012 EOF είναι ένας ειδικός χαρακτήρας, και μέσα στο <stdio.h> υπάρχει ο ορισμός του (συνήθως ορίζεται ως -1). Οπότε απλά σου λέει να βάλεις το EOF ως συνθήκη τερματισμού στο input σου. Συνήθως για να αναπαράξει ο χρήστης τον χαρακτήρα EOF από το πληκτρολόγιο πατάει Ctrl+D ή Ctrl+Z (ανάλογα την πλατφόρμα). Από την αναθεώρηση C99 και μετά μπορείς να ορίζεις μεταβλητές (άρα και πίνακες) σε οποιαδήποτε γραμμή του κώδικά σου (σε οποιοδήποτε μπλοκ βασικά) οπότε μπορείς π.χ. πρώτα να διαβάζεις από τον χρήστη το μέγεθος σε μια μεταβλητή και κατόπιν να τη χρησιμοποιείς για να φτιάξεις τον πίνακα... > ... size_t maxsize=0U; printf("Enter size for the array: "); scanf("%u", &maxsize); if ( size < 1 ) { /* άκυρο μέγεθος, deal with it */ } int array[ maxsize ] = {0}; ... Πριν από την αναθεώρηση C99 γινόταν με malloc()/calloc() ... > ... int *array = NULL; size_t maxsize=0U; printf("Enter size for the array: "); scanf("%u", &maxsize); if (maxsize > 0) array = calloc(size, sizeof(int) ); if ( !array ) { /* απέτυχε το calloc(), deal with it */ } ... Για να τα ξεκαθαρίσω λίγο η εντολή >myArray = ( int * )malloc( 5 * sizeof( int ) ); κανονικά δεσμεύει μνήμη μόνο για 5 ints έτσι δεν είναι? Μου είπες επίσης να μην χρησιμοποιώ την συνάρτηση gets. Μπορώ στη θέση της να χρησιμοποιώ την fgets, σώστα? Έχω μπερδευτεί λίγο με το 2ρο όρισμα που παίρνει μπορείς να μου το εξηγήσεις λίγο? Για το EOF δεν καταλαβαίνω πως μπορώ να το κάνω. Αφου το κείμενο θα είναι συνεχόμενο, δεν θα δίνω κάθε φορά και απο μία λέξη. Αυτό που έχω εγώ στο μυαλό μου για την EOF είναι σαν να την έχουμε τιμή φρουρός σε μια επανάληψη. Επίσης εγώ υποτίθεται ότι δεν ξέρω πιο θα είναι το μέγεθος του κειμένου, πως μπορώ να αποθηκεύσω σε μεταβλητή το μέγεθος του και μετά να φτιάξω πίνακα? Ως προς το μήκος των συμβολοσειρών, αναφέρεται στην εκφώνηση ότι μία λέξη έχει μέγιστο μήκος 100, άρα μπορείς με ασφάλεια να φτιάξεις (όπου χρειαστείς) πίνακες των 101 χαρακτήρων για να τις αποθηκεύσεις. Δεν το έπιασα αυτό Υπάρχει ασάφεια στην εκφώνηση ως προς την αρχική εισαγωγή του Αγγλικού κειμένου. Αν πρόκειται για κείμενο απροσδιόριστου μέγιστου μήκους, μια συνηθισμένη υλοποίηση είναι η δέσμευση μνήμης ανά τμήματα (chunks) καθώς πληκτρολογεί ο χρήστης, με χρήση της realloc() για κάθε επιμήκυνση. Πώς μπορώ να κάνω κάτι τέτοιο? Έχω μπερδευτεί λίγο με την άσκηση. Έριξα μία ματία στο 2ο ερώτημα και λεέι (β) καταγράφει για κάθε διαφορετική λέξη του κειμένου το πλήθος των διαφορετικών γραμμών στις οποίες εμφαίζεται Πως στο καλό θα το κάνω αυτό? Μήπως πρέπει ο πίνακας που θα αποθηκεύω τα strings να είναι 2d? Δηλαδή η κάθε γραμμή του πίνακα να αντιπροσωπεύει μια γραμμή κειμένου?
migf1 Δημοσ. 6 Ιανουαρίου 2012 Δημοσ. 6 Ιανουαρίου 2012 Η άσκηση δεν είναι εύκολη και από τον κώδικα που έχεις παραθέσει και από τις ερωτήσεις που μας κάνεις ( κάνεις πολύ καλά που ρωτάς ) δυστυχώς νομίζω πως δεν είσαι σε θέση να τη λύσεις. Δείχνεις να έχεις πάρα πολλά κενά για να λύσεις τέτοια άσκηση. Στο link της υπογραφής μου έχω κάτι σημειώσεις που προσπαθώ να εξηγήσω στα Ελληνικά τα strings, τους pointers και τις simply linked lists... ρίξε μια ματιά μήπως σε βοηθήσουν. Αλλιώς ξαναδιάβασε τα βιβλία σου περί strings, δεικτών, δομών δεδομένων και δυναμική διαχείριση μνήμης. Όσο για την ανάγνωση κειμένου απροσδιόριστου μήκους, ορίστε μια πιθανή υλοποίηση με χρήση της realloc() κάθε 128 χαρακτήρες ... η ανάγνωση γίνεται στην input_string_eof() ... > #include <stdio.h> #include <stdlib.h> #include <string.h> /* Constans & Macros ================= */ #define CHARS_CHUNK 128 /* to realloc chars during input */ #define FREESAFE( p ) \ do { \ if ( (p) ) { \ free( (p) ); \ (p) = NULL; \ } \ } while(0) /* Custom Types ====================== */ typedef enum Bool { FALSE=0, TRUE } Bool; /* Global Variables ---- */ const Bool DEBUG = TRUE; /* set to FALSE to prevent debugging msgs */ /* Function Prototypes =============== */ char *input_string_eof( const char *prompt ); Bool output_string( const char *string ); /* Function Definitions ============== */ /* ------------------------------------------------------------------------ * * ------------------------------------------------------------------------ */ int main( void ) { char *text = NULL; text = input_string_eof( "Πληκτρολογήστε κείμενο, τερματισμένο με Ctrl+Z σε νέα γραμμή\n\n" ); if ( !text ) goto exit_failure; output_string( text ); FREESAFE( text ); system("pause"); exit( EXIT_SUCCESS ); exit_failure: system("pause"); exit( EXIT_FAILURE ); } /* ------------------------------------------------------------------------ * * ------------------------------------------------------------------------ */ char *input_string_eof( const char *prompt ) { extern const Bool DEBUG; char *string = NULL, *cp = NULL, *temp = NULL; size_t i = 0, textsize = (CHARS_CHUNK+1) * sizeof(char); if ( prompt ) printf("%s", prompt); if ( (string = malloc( textsize )) == NULL ) goto ret_fatal; if ( DEBUG ) printf("\t(string successfully created with %zu bytes)\n", textsize); for (i=0U,cp=string; (*cp = getchar()) != EOF; cp++,i++ ) { if ( i != 0 && i % CHARS_CHUNK == 0 ) { textsize += CHARS_CHUNK * sizeof(char); temp = realloc(string, textsize); if ( !temp ) { FREESAFE( string ); goto ret_fatal; } if ( DEBUG ) printf("\t(string successfully resized to %zu bytes)\n", textsize ); string = temp; cp = string + i; } } *cp = '\0'; return string; ret_fatal: fprintf(stderr, "%s: fatal error: out of memory", __func__); return NULL; } /* ------------------------------------------------------------------------ * * ------------------------------------------------------------------------ */ Bool output_string( char *string ) { if ( !string ) return FALSE; while ( *string ) putchar( *string++ ); return TRUE; } Η συγκεκριμένη υλοποίηση απλώς διαβάζει χαρακτήρες και τους αποθηκεύει στο c-string: text. Εσένα η άσκηση σου ζητάει να καταγράφεις ταυτόχρονα και να υπολογίζεις κι άλλα πράγματα. Αυτό με τη ευρύτερη έννοια ονομάζεται "in-place processing" ή "real-time processing". Αν σου επιτρέπεται να διαβάσεις πρώτα το text και τα υπόλοιπα να τα υπολογίσεις σε 2ο ενδεχομένως και σε 3ο pass ίσως είναι λίγο πιο εύκολο, αλλά από την εκφώνηση εγώ καταλαβαίνω πως ζητάει σε real-time. Αυτά τα πράγματα συνήθως λύνονται με hash-tables, αλλά εφόσον ακόμα δεν έχεις εξοικείωση με τα απλά malloc()/callo() και τα strings, τα hash-tables και οι linked-lists είναι τελείως... out of question. Χρειάζεσαι διάβασμα για να τη λύσεις (κι αν το έχω πιάσει σωστά, μάλλον χρειάζεσαι ΠΟΛΥ διάβασμα για αυτή την άσκηση). EDIT: Ctrl+Z είναι το EOF στο cmd.exe των Windows, στα Unix/Linux shells νομίζω είναι Ctrl+D (ίσως να είναι κι εκεί Ctrl+Z, δεν το θυμάμαι).
παπι Δημοσ. 6 Ιανουαρίου 2012 Δημοσ. 6 Ιανουαρίου 2012 Μια τεραστια υλοποιηση για να διαβασεις εως το εοφ >char *buffer; int bufferSize; int main(int argc, char **argv) { buffer = (char*)malloc(0x7fffu); bufferSize = fread(buffer,1,0x7fffu,stdin); free(buffer); return 0; }
migf1 Δημοσ. 6 Ιανουαρίου 2012 Δημοσ. 6 Ιανουαρίου 2012 Αυτό αφενός δεν τον εξυπηρετεί για real-time κι αφετέρου δεν έχει απροσδιόριστο μέγεθος input.
παπι Δημοσ. 6 Ιανουαρίου 2012 Δημοσ. 6 Ιανουαρίου 2012 Πραγματι τωρα βγενει πολυυυυυυυυ μεγαλο >char *buffer; int bufferSize; #define N (1024u * 10u) int main(int argc, char **argv) { int readed; do { buffer = (char*) realloc(buffer, N + bufferSize); readed = fread(buffer + bufferSize,1,N,stdin); bufferSize += readed; }while(!feof(stdin)); free(buffer); return 0; }
migf1 Δημοσ. 6 Ιανουαρίου 2012 Δημοσ. 6 Ιανουαρίου 2012 Και πως ακριβώς θα μετρήσει λέξεις και γραμμές (και θα σώσει και λέξεις) real-time με τον κώδικά σου; EDIT: Btw, αν αποτύχει το realloc(), ο κώδικάς σου δεν δουλεύει. Επίσης, καλείς το realloc() με undefined buffer. Ακόμα, εφόσον χρησιμοποιείς το realloc() με την C99 εκδοχή του (αφού πρώτα το αρχικοποιήσεις σε NULL, όπως πρέπει) δεν χρειάζεται το cast.
AMIOX? Δημοσ. 6 Ιανουαρίου 2012 Δημοσ. 6 Ιανουαρίου 2012 Διάβασμα εώς το eof γίνετε και έτσι: > #include<stdio.h> #include<stdlib.h> int main(void) { char *text; int i=0; text=(char *)calloc(1,1); *(text+i)=getc(stdin); while(*(text+i)!=EOF) { text=(char *)realloc(text,++i+1); *(text+i)=getc(stdin); } *(text+--i)='\0'; }
migf1 Δημοσ. 6 Ιανουαρίου 2012 Δημοσ. 6 Ιανουαρίου 2012 Διάβασμα εώς το eof γίνετε και έτσι: > #include<stdio.h> #include<stdlib.h> int main(void) { char *text; int i=0; text=(char *)calloc(1,1); *(text+i)=getc(stdin); while(*(text+i)!=EOF) { text=(char *)realloc(text,++i+1); *(text+i)=getc(stdin); } *(text+--i)='\0'; } Αυτό είναι το πιο inefficient implementation που μπορεί να κάνει κάποιος, με realloc() σε κάθε χαρακτήρα! Έχεις επίσης το ίδιο πρόβλημα με τον κώδικα του πάπι, δηλαδή όχι μόνο δεν ελέγχετε για αποτυχία του realloc() αλλά δεν το κάνετε και σε προσωρινό δείκτη, έτσι ώστε αν αποτύχει να μην χάσετε τον αυθεντικό δείκτη του text. ΥΓ. Και τελικά το cast δεν χρειάζεται ούτε σε C89 ... Επίσης, καλείς το realloc() με undefined buffer.. Άκυρο κι απολογούμαι για το συγκεκριμένο, αρχικοποιημένο είναι το buffer (τώρα πρόσεξα πως το ορίζεις καθολικά, άρα αρχικοποιείται αυτόματα σε 0 ... που ισοδυναμεί με NULL),
παπι Δημοσ. 6 Ιανουαρίου 2012 Δημοσ. 6 Ιανουαρίου 2012 Btw, αν αποτύχει το realloc(), ο κώδικάς σου δεν δουλεύει. Επίσης, καλείς το realloc() με undefined buffer. Ακόμα, εφόσον χρησιμοποιείς το realloc() με την C99 εκδοχή του (αφού πρώτα το αρχικοποιήσεις σε NULL, όπως πρέπει) δεν χρειάζεται το cast. BSS φιλτατε
Προτεινόμενες αναρτήσεις
Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε
Πρέπει να είστε μέλος για να αφήσετε σχόλιο
Δημιουργία λογαριασμού
Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!
Δημιουργία νέου λογαριασμούΣύνδεση
Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.
Συνδεθείτε τώρα