migf1 Δημοσ. 12 Ιανουαρίου 2012 Δημοσ. 12 Ιανουαρίου 2012 Νομίζω πως σας έχω μερικά καλά και μερικά άσχημα νέα. Τα καλά νέα είναι πως σας έγραψα κώδικα που κάνει την περισσότερη από τη δουλειά που ζητάει η άσκηση. Τα άσχημα νέα είναι πως αφενός έχω αφήσει επίτηδες κάποια κομμάτια χωρίς καθόλου σχόλια κι αφετέρου πως επίσης επίτηδες ούτε έχω υλοποιήσει όλα όσα ζητάει η άσκηση ούτε ακριβώς όπως τα ζητάει. Ο κώδικάς κάνει τα εξής: 1. Ζητάει από τον χρήστη να πληκτρολογήσει το Αγγλικό κείμενο και να πατήσει Ctrl+Z σε νέα γραμμή για σηματοδότηση τέλους (αν είστε σε Unix/Linux περιβάλλον πρέπει να πατήσει Ctr+D) 2. Το Αγγλικό κείμενο διαβάζεται σε τμήματα των 128 χαρακτήρων που προστίθενται σταδιακά καθώς πληκτρολογεί ο χρήστης, και επεξεργάζεται σε πραγματικό χρόνο (in place) σύμφωνα με το επόμενο βήμα. 3. Η inplace επεξεργασία του 2ου βήματος περιλαμβάνει: α) real-time διαχωρισμό του κειμένου σε έγκυρες λέξεις (όσες αρχίζουν από γράμμα) β) προσθήκη μόνο των έγκυρων λέξεων σε απλά συνδεδεμένη λίστα γ) ενημέρωση του πλήθους εμφανίσεών κάθε έγκυρης λέξης στο κείμενο δ) ενημέρωση του πλήθους των γραμμών στις οποίες εμφανίζεται η κάθε έγκυρη λέξη. 4. Η εισαγωγή των έγκυρων λέξεων στη λίστα γίνεται απευθείας στη σωστή τους αλφαβητική σειρά (η χρήση του δείκτη tail επισπεύδει τον μέσο χρόνο της διαδικασίας) 5. Εμφανίζει στην οθόνη το μενού με τις 3 επιλογές που ζητάει η άσκηση. Η επιλογή "(3) Έξοδος" τερματίζει το πρόγραμμα, οι άλλες 2 συμπεριφέρονται ακριβώς όμοια, σύμφωνα με το επόμενο βήμα. 6. Ζητείται από τον χρήστη μια λέξη. Η λέξη αναζητείται στη λίστα και το πρόγραμμα ενημερώνει αν βρέθηκε η όχι. Ο κώδικας ΔΕΝ κάνει τα εξής: 1. Δεν αφαιρεί τυχόν σημεία στίξης από τα τέλη των έγκυρων λέξεων (αυτό διορθώνεται πανεύκολα με μια μόλις αλλαγή σε μια από τις συνθήκες if της: handle_input_inplave() ) 2. Δεν χρησιμοποιεί ξεχωριστή συνάρτηση για την αναγνώριση και τον διαχωρισμό των λέξεων στο αρχικό κείμενο (περισσότερα παρακάτω) 3. Δεν υλοποιεί τις 2 πρώτες επιλογές του μενού (σας έχω όμως συμπεριλάβει συνάρτηση για μαζικό τύπωμα όλης της λίστας). Σημειώσεις Όλη η βρώμικη δουλειά γίνεται στη συνάρτηση: handle_input_inplace() η οποία και μεγάλη είναι και δύσκολη στην κατανόησή της σε όσους έχουν βασικές ελλείψεις υπόβαθρου. Ακριβώς λόγω της δυσκολίας της, τελικά αμφιβάλλω αν όντως θέλει να τα κάνετε όλα αυτά inplace. Αυτό ενισχύεται κι από το γεγονός πως η εκφώνηση (μου την στείλατε ολόκληρη και σε pm) ζητάει η αναγνώριση των λέξεων να γίνεται σε ξεχωριστή συνάρτηση. Σε αυτή την περίπτωση είναι πολύ πιο εύκολα τα πράγματα, μιας και μπορείτε να διαβάσετε το Αγγλικό κείμενο σε ένα pass, να κάνετε τον διαχωρισμό των λέξεων σε 2ο pass και την καταγραφή τους στη λίστα ενδεχομένως σε 3ο pass (τα 2 τελευταία passes καλύτερα να τα συμπτύξετε σε 1, που και εύκολο είναι και μέσα στις προδιαγραφές της εκφώνησης). Για το 1ο pass που απλά θα διαβάζει το Αγγλικό κείμενο, δείτε την απάντηση που έχει δώσει ο παπι σε αυτό το νήμα. Για το 2ο pass μπορείτε να πάρετε ιδέες από τον κώδικα της handle_input_inplace(), αλλά θα σας συνιστούσα αντί αυτού να το κάνετε με χρήση της συνάρτησης strtok(). Σε ότι αφορά την υλοποίηση στο δικό μου κώδικα, η λίστα (WList) αποτελείται από head και tail, ενώ ο κάθε κόμβος της (WNode) εκφράζει μια μόνο λέξη. Αλγοριθμικά είναι ΑΡΓΗ υλοποίηση, για να μείνει σε απλά επίπεδα ο κώδικας. Αλλιώς μπορείτε για παράδειγμα να του προσθέσετε hash-table για τα 127 πρώτα σύμβολα του ASCII table (ή και τα 256 αν προτίθεστε να υποστηρίξετε 8μπιτες κωδικοποιήσεις αντί για την 7μπιτη Λατινκή). Μπορείτε επίσης να τροποποιήστε την wlist_lookup_word() ώστε αντί για sequential search να κάνει binary search. Γενικώς υπάρχουν πολλοί και διάφοροι τρόποι υλοποίησης, η συντριπτική πλειοψηφία των οποίων είναι πιο efficient από αυτόν τον κώδικα. ΓΙΑΤΙ ΣΑΣ ΔΙΝΩ ΕΤΟΙΜΟ ΚΩΔΙΚΑ 1. Για να βοηθηθείτε όσοι όντως ενδιαφέρεστε να μάθετε προγραμματισμό ή/και C 2. Για να δώσω κίνητρο και σε αυτούς που μισο-ενδιαφέρονται να ενδιαφερθούν πραγματικά 3. Διότι αν δεν ασχοληθείτε κι απλώς κάνετε copy & paste τον δικό μου κώδικα, δεν πρόκειται να πάρετε καλό βαθμό ... το πιθανότερο είναι να σας μηδενίσει την εργασία ως μη δική σας (αντίθετα με την ευρέως διαδεδομένη φήμη, οι καθηγητές/διορθωτές ΔΕΝ τρώνε κουτόχορτο) 4. Διότι ο κώδικας αυτός δεν είναι ΣΕ ΚΑΜΙΑ ΠΕΡΙΠΤΩΣΗ βελτιστοποιημένος. Γράφτηκε σε λιγότερο από 2 ώρες, απλά και μόνο για τις ανάγκες αυτού του νήματος και να σας δώσει κίνητρο να ασχοληθείτε παραπέρα. 5. Διότι μου είναι αδύνατον να κοιτάω έναν-έναν τους κώδικες που μου στέλνετε σε π.μ. και μου ζητάτε να τους δω και να σας πω που έχετε λάθη !!! Παραθέτω τον κώδικα: > #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> /* Constans & Macros ================= */ #define MAXINPUT (1023+1) #define CHARS_CHUNK 128 /* size of realloc chunk during input, in chars */ #define MAXWORDSIZE (100+1) #define MIN(x,y) ( (x) < (y) ? (x) : (y) ) #define VALID_MSEL( sel ) ( (sel) > MSEL_START && (sel) < MSEL_END ) #define SPITERROR( text ) \ fprintf(stderr, "\n*** ERROR in %s(): %s\n\n", __func__, text ) #define FREESAFE( p ) \ do { \ if ( (p) ) { \ free( (p) ); \ (p) = NULL; \ } \ } while(0) /* Custom Types ====================== */ typedef enum Bool { FALSE=0, TRUE } Bool; enum MSel { MSEL_START=0, MSEL_ALL, MSEL_LINES, MSEL_EXIT, MSEL_END }; typedef struct WNode WNode; /* word node */ struct WNode { char word[ MAXWORDSIZE ]; int ntimes; int nlines; size_t curln; WNode *next; }; typedef struct WList { /* word list */ WNode *head; WNode *tail; } WList; /* Global Variables ---- */ const Bool DEBUG = TRUE; /* set to FALSE to prevent debugging msgs */ /* Function Prototypes =============== */ Bool handle_input_inplace( const char *prompt, WList *wlist ); enum MSel menu_choice( void ); // char *input_string_eof( const char *prompt ); Bool prompt_for_int ( const char *prompt, int *integer ); Bool prompt_for_string( const char *prompt, char *string ); Bool output_string( const char *string ); Bool wnode_set_data( WNode *wnode, const char *word, /*const int ntimes,*/ const int curline); Bool wlist_update ( WList *wlist, const WNode *data ); WNode *wlist_lookup_word( const WList *wlist, char *word ); void wlist_print ( const WList *wlist ); void wlist_destroy ( WList *wlist ); /* Function Definitions ============== */ /* ------------------------------------------------------------------------ * * ------------------------------------------------------------------------ */ int main( void ) { WList wlist = { NULL, NULL }; /* list of valid words (from text) */ int msel = 2; /* user selection from menu */ char word[MAXWORDSIZE] = {'\0'}; /* word to be looked for */ if ( !handle_input_inplace( "Πληκτρολογήστε κείμενο, τερματισμένο με Ctrl+Z σε νέα γραμμή\n\n", &wlist ) ) { goto exit_failure; } if ( DEBUG ) wlist_print( &wlist ); while ( MSEL_EXIT != (msel=menu_choice()) ) { prompt_for_string( "\nΛέξη προς αναζήτηση: ", word ); printf("\tη λέξη %sβρέθηκε!\n", wlist_lookup_word( &wlist, word ) ? "\0" : "Δεν "); } wlist_destroy( &wlist ); exit( EXIT_SUCCESS ); exit_failure: wlist_destroy( &wlist ); exit( EXIT_FAILURE ); } /* ------------------------------------------------------------------------ * * ------------------------------------------------------------------------ */ Bool handle_input_inplace( const char *prompt, WList *wlist ) { extern const Bool DEBUG; char *text = NULL; /* the text to be read */ char *cp = NULL; /* to read chars from stdin into text */ char *wsp = NULL; /* ptr to start of current word (ws) */ size_t wsi = 0U; /* wsp pos in text (for after realloc)*/ Bool wsInvalid = FALSE; /* is start of current word non-alpha?*/ char word[MAXWORDSIZE] = {'\0'}; /* to store the current word */ WNode wdata = {{'\0'}, 0, 0, 0, NULL};/* to store cur word's node data */ char *temp = NULL; /* to try realloc before accepting it */ size_t textsize = (CHARS_CHUNK+1) * sizeof(char);/* mem chunksize for realloc */ size_t i = 0U, ln=0U; /* to count chars & lines respectively*/ if ( prompt ) /* display the prompt, if any */ printf("%s", prompt); if ( (text = malloc( textsize )) == NULL ) /* allocate initial mem for text */ goto ret_fatal; if ( DEBUG ) printf("\t(text successfully created with %u bytes)\n", textsize); ln = 0U; /* lines counter */ wsp = NULL; /* points to start of current word */ wsInvalid = FALSE; /* assume word-start will be alpha */ for (i=0U, cp=text; (*cp = getchar()) != EOF; cp++,i++ ) { if ( !isalpha(*cp) && !wsInvalid ) /* curr char is non-alpha word-start */ wsInvalid = TRUE; /* ... set invalid-word-start status */ if ( isalpha(*cp) && !wsInvalid ) /* current char is alpha word-start */ { if ( !wsp ) { /* ... remember char as word-start */ wsp = cp; wsi = i; } } /* * !!! The rest of the loop is left UNCOMMENTED intentionally !!! */ if ( isspace(*cp) ) { if ( *cp == '\n') ln++; if ( wsp ) { memcpy( word, wsp, MIN( cp-wsp, MAXWORDSIZE ) ); word[ (cp-wsp) ] = '\0'; wsp = NULL; wnode_set_data( &wdata, word, /*0,*/ ln); wlist_update( wlist, &wdata); } wsInvalid = FALSE; /* set valid-word-start status */ } /* check if text needs reallocation (i.e. user keeps typing beyond curr size) */ if ( i != 0 && i % CHARS_CHUNK == 0 ) { textsize += CHARS_CHUNK * sizeof(char); temp = realloc(text, textsize); if ( !temp ) goto ret_fatal; if ( DEBUG ) printf("\t(text resized to %u bytes)\n", textsize ); text = temp; cp = text + i; wsp = text + wsi; } } *cp = '\0'; if ( DEBUG ) output_string( text ); FREESAFE( text ); return TRUE; ret_fatal: fprintf(stderr, "%s: fatal error: out of memory", __func__); FREESAFE( text ); wlist_destroy( wlist ); return FALSE; } /* ------------------------------------------------------------------------ * * ------------------------------------------------------------------------ */ enum MSel menu_choice( void ) { enum MSel ret = MSEL_START; do { puts( "\n ====================================" ); puts( " ΣΤΑΤΙΣΤΙΚΑ ΛΕΞΕΩΝ \n"); puts( " 1) Συνολικές εμφανίσεις λέξεως"); puts( " 2) Πλήθος γραμμών που περιέχουν τη λέξη"); puts( " 3) ΕΞΟΔΟΣ"); puts( " ====================================\n"); prompt_for_int( "> ", (int *)&ret ); } while ( !VALID_MSEL(ret) ); return ret; } /* ------------------------------------------------------ * * ------------------------------------------------------ */ Bool prompt_for_int( const char *prompt, int *integer ) { char input[ MAXINPUT ] = {'\0'}; if ( !integer ) { SPITERROR( "integer is undefined!" ); return FALSE; } if ( prompt ) printf("%s", prompt); fgets( input, MAXINPUT, stdin ); *integer = atoi( input ); return TRUE; } /* ------------------------------------------------------ * * ------------------------------------------------------ */ Bool prompt_for_string( const char *prompt, char *string ) { if ( !string ) { SPITERROR("string is undefined!"); return FALSE; } if ( prompt ) printf("%s", prompt); fgets( string, MAXWORDSIZE, stdin ); string[ strlen(string)-1 ] = '\0'; /* afairesh toy '\n' */ return TRUE; } /* ------------------------------------------------------------------------ * * ------------------------------------------------------------------------ */ Bool output_string( const char *string ) { if ( !string ) return FALSE; while ( *string ) putchar( *string++ ); return TRUE; } /* ------------------------------------------------------ * * ------------------------------------------------------ */ Bool wnode_set_data( WNode *wnode, const char *word, /* const int ntimes,*/ const int curline) { if ( !wnode || !word ) { SPITERROR( "undefined wnode or undefined word!" ); return FALSE; } strncpy(wnode->word, word, MAXWORDSIZE); wnode->ntimes = 0; /* this may be anything here (it gets auto-updated) */ wnode->nlines = 0; /* this may be anything here (it gets auto-updated) */ wnode->curln = curline; return TRUE; } /* ------------------------------------------------------ * * ------------------------------------------------------ */ Bool wlist_update( WList *wlist, const WNode *data ) { WNode *curr = NULL, *prev = NULL; WNode *new = calloc( 1, sizeof(WNode) ); if ( !new ) /* calloc failed */ return FALSE; memcpy( new, data, sizeof(WNode) ); new->next = NULL; /* when wlist is empty, add new to the wlist */ if ( wlist->head == NULL) { wlist->head = wlist->tail = new; new->ntimes = 1; new->nlines = 1; return TRUE; } /* when new's word matches tail's, update tail & free new */ if ( strcmp(new->word, wlist->tail->word) == 0 ) { if ( new->curln != wlist->tail->curln ) { wlist->tail->curln = new->curln; (wlist->tail->nlines)++; } (wlist->tail->ntimes)++; free( new ); return TRUE; } /* when new's word is greater than tail's, append new to the wlist */ if ( strcmp(new->word, wlist->tail->word) > 0 ) { new->ntimes = 1; new->nlines = 1; wlist->tail->next = new; wlist->tail = new; return TRUE; } /* otherwise traverse the wlist (general case) */ curr = prev = wlist->head; while (curr && strcmp(curr->word, new->word ) < 0) /* (use <= to allow duplicates) */ { prev = curr; /* save previous node */ curr = curr->next; } /* new's word matches current node's, update current node & free new */ if ( curr && strcmp(curr->word, new->word ) == 0 ) { if ( curr->curln != new->curln) { curr->curln = new->curln; (curr->nlines)++; } (curr->ntimes)++; free( new ); return TRUE; } /* new's word is less than head's, prepend new to the wlist */ if ( wlist->head == curr && strcmp(curr->word, new->word) != 0 ) { new->ntimes = 1; new->nlines = 1; wlist->head = new; new->next = curr; return TRUE; } /* new's word was not found in the wlist, insert new between prev & curr */ if ( !curr || curr->word != new->word ) { new->ntimes = 1; new->nlines = 1; prev->next = new; new->next = curr; } return TRUE; } /* ------------------------------------------------------ * * ------------------------------------------------------ */ WNode *wlist_lookup_word( const WList *wlist, char *word ) { WNode *temp = wlist->head; while ( temp ) { if ( strcmp(word, temp->word) == 0 ) break; temp = temp->next; } return temp; } /* ------------------------------------------------------ * * ------------------------------------------------------ */ void wlist_print( const WList *wlist ) { WNode *temp = wlist->head; while ( temp ) { printf( "\t%s %d %d\n", temp->word, temp->ntimes, temp->nlines ); temp = temp->next; } putchar('\n'); return; } /* ------------------------------------------------------ * * ------------------------------------------------------ */ void wlist_destroy( WList *wlist ) { WNode *dummy = NULL; while ( wlist->head != NULL ) { dummy = wlist->head->next; free( wlist->head ); wlist->head = dummy; } return; } ΥΓ. Τον έχω τεστάρει στα γρήγορα και δείχνει να λειτουργεί as expected σε GCC. Σε Pelles-C μπαίνει σε infinite-loop με το μενού αμέσως μετά το Ctrl+Z. Αυτό είναι πρόβλημα της Pelles-C με το Ctrl+Z και όχι του κώδικα. (αλλάξτε το EOF στον κώδικα με κάποιον άλλον χαρακτήρα για τη σηματοδότηση τέλους και θα δουλεύει και με Pelles-C). Παρόλα αυτά είναι παραπάνω από πιθανό να περιέχει bugs ο κώδικας! Τσεκάρετέ τον μόνοι σας,
TheOneGandalf Δημοσ. 12 Ιανουαρίου 2012 Μέλος Δημοσ. 12 Ιανουαρίου 2012 Η αλήθεια είναι ότι τις ασκήσεις τις παρέδωσα χθές. Όσο αφορά αυτήν την άσκηση κατάφερα να την λύσω, ύστερα απο πολύ κόπο! Το κομμάτι που απαιτούσε να διαβάσουμε το κέιμενο άγνωστου πλήθους το υλοποίησα ( η πιο σωστά, το αντέγραψα ) απο τον κώδικα του AMIOX?. Ο λόγος που χρησιμοποίησα αυτόν τον κώδικα ήταν διότι ήταν μικρός και κατάλαβα πως δούλευε και μου φάνηκε 'εύκολος'. Επειδή τώρα πλησιάζει η εξεταστική και εχω πολυυυ διάβασμα και μερικές ακόμα εργασίες να παραδώσω για άλλα μαθήματα δεν έχω χρόνο να κοιτάξω τον κώδικα που έγραψες για αυτήν την άσκηση και την άλλη με τις λίστες και τα βιβλία. Ωστόσο επειδή με ενδιαφέρει πολύ ο προγραμματισμός, μετά την εξεταστική σίγουρα θα ξαναπιάσω την C. θα καλύψω τα κενά που έχω και μετα ποιος με πιάνει!! Τότε λοιπόν που θα έχω χρόνο θα ξαναπιάσω αυτές τις 'δυνατές' ασκήσεις, θα κοιτάξω τον κωδικά σου και θα προσπαθήσω και εγώ να τις υλοποιήσω πάλι όσο καλύτερα μπορώ! Σε αυτό το σημείο θέλω να σε ευχαριστήσω γιατί μέσα απο τις σημειώσεις σου τα πόστ σου και τον κώδικα σου κατάφερα να μάθω πολλά πράγματα. Τώρα πια τους δείκτες τους βλέπω σαν όπλο και όχι σαν κάτι που πρέπει οπωςδήποτε να αποφύγω!! Έχω να σε ρωτήσω και κάτι τελευταίο. Ένα πράγμα που πραγματικά δεν μπορώ να εξηγήσω γιατί συμβαίνει. Σαν IDE χρησιμοποιώ τον Pelles C. Όταν ήρθε η ώρα να τρέξω μερικά προγράμματα στο περιβάλλον που χρησιμοποιεί η σχολή μου( Unix και κάποιον αρχαίο compiler προφανώς ) αντιμετώπισα ένα παράξενο 'bug'. Για παράδειγμα την άσκηση την οποία πόσταρα προχθες( εκείνη με την βιβλιοθήκη ), όταν πάταγες το 1 έπρεπε να σου εμφανίσει ( δώσε ονομα συγγραφέα, ονομα βιβλίου κλπ ) αλλά κοίτα τι γινότανε Dwse onoma syggrafea : Dwse onoma vivliou : Δηλαδή δεν με άφηνε να διαβάσω το όνομα του συγγραφέα, αλλά μόνο το όνομα του βιβλίου. Κάτι σαν να 'πήδαγε' την gets που είχα για είσοδο του ονόματος συγγραφέα. Αυτο γινότανε και αν πάταγα την επιλογή 2 ή 3 ( να δανειστώ κάποιο βιβλίο ή να έδινε το όνομα ενός και να μου εμφάνιζε τα στοιχεία του ). Δηλαδή εμφάνιζε Dwse to onoma tou vivliou pou thes na danisteis : και μετά αν θυμάμαι καλά μου εμφάνιζε ξανα το μενού, δηλαδή πάλι δεν με άφηνε να διαβάσω. Δοκίμασα πολλά πράγματα. Να χρησιμοποιήσω την fgets, να βάλω 2 gets αλλά τίποτα . Τελικά κατάφερα να το λύσω με μια 'πατέντα' . Έβαλα ένα μετρητή i και τον αρχικοποίησα με 1. Και εκει που έπρεπε να διάβαζε το έκανα έτσι > fflush( stdin ); gets( vivlio ); if ( i >= 1 ) { fflush( stdin ); gets( vivlio ); } και δούλεψε έτσι!! . Στον Pelles C έτρεχε κανονικά. Ωστόσο έχω πάθει αντίστοιχο πρόβλημα και στον Pelles C με άλλες ασκήσεις! Ο καθηγητής μας στο forum της σχολής μας που αναφέραμε αυτό το πρόβλημα( το είχανε και άλλα παιδία ) μας είπε να χρησιμοποιούμε την fflush() και ότι η C έχει γενικά κάποια προβλήματα όσο αφορά τις διαδικασίες εισόδου.
migf1 Δημοσ. 12 Ιανουαρίου 2012 Δημοσ. 12 Ιανουαρίου 2012 Είναι το πρόβλημα με τα απομεινάρια που αφήνουν στην κύρια είσοδο οι στάνταρ συναρτήσεις διαβάσματος της C, τα οποία τα διαβάζει κατόπιν σαν input η επόμενη συνάρτηση διαβάσματος. Την εξήγηση την έχω δώσει πολλές φορές και σε αυτό το φόρουμ, οπότε με ένα Search θα το βρεις. Εν τάχει, για να μην έχεις πρόβλημα, διάβαζε μονοκόμματα ολόκληρη τη γραμμή εισόδου με fgets σε ένα string μεγάλου μεγέθους (πάνω από 256 χαρακτήρες). Κατόπιν διάβαζε ότι θες μέσα από αυτό το string είτε με sscanf() είτε με τις συναρτήσεις ato?(). Π.χ. > #define MAXINPUT (1023+1) ... int main( void ) { int n; float x; char input[ MAXINPUT ] = {'\0'}; printf("Type an int and a float: "); fgets( input, MAXINPUT, stdin); sscanf( input, "%d %f", &n, &x); ... } Δες τις συναρτήσεις: prompt_for_???() στον κώδικα που πόσταρα σήμαρα ή τις συναρτήσεις: input_????() στον κώδικα που είχα ποστάρει στην άσκηση με τα βιβλία. Το fflush( stdin ) έχει undefined συμπεριφορά... δεν μπορείς να βασίζεσαι σε αυτό αν σε ενδιαφέρει ο κώδικάς σου να τρέχει παντού.
TheOneGandalf Δημοσ. 12 Ιανουαρίου 2012 Μέλος Δημοσ. 12 Ιανουαρίου 2012 Είναι το πρόβλημα με τα απομεινάρια που αφήνουν στην κύρια είσοδο οι στάνταρ συναρτήσεις διαβάσματος της C, τα οποία τα διαβάζει κατόπιν σαν input η επόμενη συνάρτηση διαβάσματος. Την εξήγηση την έχω δώσει πολλές φορές και σε αυτό το φόρουμ, οπότε με ένα Search θα το βρεις. Εν τάχει, για να μην έχεις πρόβλημα, διάβαζε μονοκόμματα ολόκληρη τη γραμμή εισόδου με fgets σε ένα string μεγάλου μεγέθους (πάνω από 256 χαρακτήρες). Κατόπιν διάβαζε ότι θες μέσα από αυτό το string είτε με sscanf() είτε με τις συναρτήσεις ato?(). Π.χ. > #define MAXINPUT (1023+1) ... int main( void ) { int n; float x; char input[ MAXINPUT ] = {'\0'}; printf("Type an int and a float: "); fgets( input, MAXINPUT, stdin); sscanf( input, "%d %f", &n, &x); ... } Δες τις συναρτήσεις: prompt_for_???() στον κώδικα που πόσταρα σήμαρα ή τις συναρτήσεις: input_????() στον κώδικα που είχα ποστάρει στην άσκηση με τα βιβλία. Το fflush( stdin ) έχει undefined συμπεριφορά... δεν μπορείς να βασίζεσαι σε αυτό αν σε ενδιαφέρει ο κώδικάς σου να τρέχει παντού. Οκ θα τις κοιτάξω. Ευχαριστώ και πάλι!
AMIOX? Δημοσ. 12 Ιανουαρίου 2012 Δημοσ. 12 Ιανουαρίου 2012 Αυτό είναι το πιο inefficient implementation που μπορεί να κάνει κάποιος, με realloc() σε κάθε χαρακτήρα! Έχεις επίσης το ίδιο πρόβλημα με τον κώδικα του πάπι, δηλαδή όχι μόνο δεν ελέγχετε για αποτυχία του realloc() αλλά δεν το κάνετε και σε προσωρινό δείκτη, έτσι ώστε αν αποτύχει να μην χάσετε τον αυθεντικό δείκτη του text. Συγνώμη,πρωτοετής είμαι το ξέρω πως δεν χρησιμοποιώ σωστά την realloc αλλα ηταν το μόνο που μπόρεσα να σκεφτώ. Ο καθηγητής μας στο forum της σχολής μας που αναφέραμε αυτό το πρόβλημα( το είχανε και άλλα παιδία ) μας είπε να χρησιμοποιούμε την fflush() και ότι η C έχει γενικά κάποια προβλήματα όσο αφορά τις διαδικασίες εισόδου. Αντί του fflush μπορείς να χρησιμοποιείς το παρακάτω για άδειασμα του buffer.. > while(ch=getchar()!='\n');
migf1 Δημοσ. 13 Ιανουαρίου 2012 Δημοσ. 13 Ιανουαρίου 2012 Συγνώμη,πρωτοετής είμαι το ξέρω πως δεν χρησιμοποιώ σωστά την realloc αλλα ηταν το μόνο που μπόρεσα να σκεφτώ. Βρε σεις δεν χρειάζεται να απολογείστε! Βέβαια, όταν με... ξαναδιαβάζω διαπιστώνω κι εγώ πως "βγαίνω" κάπως επιθετικός ή μάλλον επιπληκτικός (υπάρχει τέτοια λέξη; ) αλλά την ώρα που τα γράφω δεν έχω καμία τέτοια πρόθεση. Απλώς να επισημάνω πράγματα που χρίζουν βελτίωσης προσπαθώ.
AMIOX? Δημοσ. 13 Ιανουαρίου 2012 Δημοσ. 13 Ιανουαρίου 2012 Βρε σεις δεν χρειάζεται να απολογείστε! Βέβαια, όταν με... ξαναδιαβάζω διαπιστώνω κι εγώ πως "βγαίνω" κάπως επιθετικός ή μάλλον επιπληκτικός (υπάρχει τέτοια λέξη; ) αλλά την ώρα που τα γράφω δεν έχω καμία τέτοια πρόθεση. Απλώς να επισημάνω πράγματα που χρίζουν βελτίωσης προσπαθώ. Ξέρω τι θες να κάνεις! δεν απολογούμαι απλός εξηγούμαι!
Προτεινόμενες αναρτήσεις
Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε
Πρέπει να είστε μέλος για να αφήσετε σχόλιο
Δημιουργία λογαριασμού
Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!
Δημιουργία νέου λογαριασμούΣύνδεση
Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.
Συνδεθείτε τώρα