Anubis13 Δημοσ. 12 Ιουλίου 2009 Δημοσ. 12 Ιουλίου 2009 Θελω να διαβασω μια ακολουθια αριθμων απο ενα αρχειο. Παραδειγμα : 23 129 0 9 576 74 κλπ και μετα να δημιουργησω ενα δυναμικο πινακα. Το προβλημα μου ειναι το πως θα διαβασω τους αριθμους ωστε να αποφευγω τα κενα? Γνωριζω οτι η fscanf δεν μου κανει για αυτη την περιπτωση. Σκεφτομουν να διαβαζω χαρακτηρα χαρακτηρα αλλα εκει πως θα "φτιαχνω" τον αριθμο? Οπως καταλαβαινετε το προβλημα μου δεν ειναι ουτε στο ανοιγμα του αρχειου ουτε στην δημιουργια του πινακα αλλα κυριως στο διαβασμα της ακολουθιας Μπορειτε να με καθοδηγησετε?
Directx Δημοσ. 12 Ιουλίου 2009 Δημοσ. 12 Ιουλίου 2009 Μπορείς να διαβάσεις τους αριθμούς από το αρχείο διακόπτοντας όταν η fscanf επιστρέψει EOF που δηλώνει το τέλος του αρχείου ή αν επιστρέψει διαφορετικό από τον αναμενόμενο αριθμό αναγνωσμένων παραμέτρων (στην περίπτωση μας είναι το 1 διότι διαβάζουμε μόνο ένα αριθμό την φορά - %d). Τα κενά αγνοούνται αυτόματα από την ρουτίνα. Ακολουθεί ένα μικρό παράδειγμα, το οποίο διαβάζει integers από αρχείο εισόδου και τους εκτυπώνει στην οθόνη. > /* Read numbers from file with fscanf dx */ #include <stdio.h> int main(int argc, char* argv[]) { FILE *fStream = NULL; /* Open file for text reading */ if((fStream = fopen(argv[1], "rt")) != NULL) { int nNumber, nS; /* Read up to EOF */ while((nS = fscanf(fStream, "%d", &nNumber)) != EOF) if(!nS) /* or up to first invalid data */ { printf("*** Invalid file data, review offset: %ld ***\n", ftell(fStream)); break; } else /* print valid data on stdout */ printf("%d\n", nNumber); /* Close stream */ fclose(fStream); } else /* open error! */ printf("Cannot open file for read - %s\n", argv[1]); /* End of program */ printf("Press Enter to exit.."); getchar(); return 0; } Αρχείο εισόδου: > 23 129 0 9 576 74 Έξοδος: > 23 129 0 9 576 74 Press Enter to exit.. Καλή συνέχεια!! Υ.Γ. Το πρόγραμμα έχει δοκιμασθεί σε ET/CodeGear C/C++ Builder και μπορεί να περιέχει bugs ή άλλες αβλεψίες.
Amadeus7 Δημοσ. 13 Ιουλίου 2009 Δημοσ. 13 Ιουλίου 2009 επίσης μπορείς να τα παρεις ολα με fgets και μετα να τα κοψεις και να τα κανεις integers με strtok (και χαρακτήρας διαχωρισμού το "κενο") και με atoi αντίστοιχα.
Anubis13 Δημοσ. 13 Ιουλίου 2009 Μέλος Δημοσ. 13 Ιουλίου 2009 επίσης μπορείς να τα παρεις ολα με fgets και μετα να τα κοψεις και να τα κανεις integers με strtok (και χαρακτήρας διαχωρισμού το "κενο") και με atoi αντίστοιχα. θα μπορουσες να μου δωσεις ενα παραδειγμα?
Evgenios1 Δημοσ. 13 Ιουλίου 2009 Δημοσ. 13 Ιουλίου 2009 Πρεπει να ειναι text file?? Γιατι δε πας σε binary??┘
Anubis13 Δημοσ. 13 Ιουλίου 2009 Μέλος Δημοσ. 13 Ιουλίου 2009 Ναι ο τυπος του αρχειου ειναι συγκεκριμενος..Τι θα κερδιζα με Binary?
Evgenios1 Δημοσ. 13 Ιουλίου 2009 Δημοσ. 13 Ιουλίου 2009 Ναι ο τυπος του αρχειου ειναι συγκεκριμενος..Τι θα κερδιζα με Binary? 1) speed 2) speed 3) speed 4) μεγεθος
Directx Δημοσ. 13 Ιουλίου 2009 Δημοσ. 13 Ιουλίου 2009 Με fgets και atoi μπορεί να γίνει έτσι: > /* Read numbers from file with fgets/atoi or sscanf dx */ #include <stdio.h> #include <string.h> #include <stdlib.h> /* C preprocessor commands */ /* #define _SSCANF #define _WITHGOTO */ int main(int argc, char* argv[]) { FILE *fStream = NULL; char szLine[bUFSIZ]; #ifndef _WITHGOTO int nDataErr = 0; #endif if((fStream = fopen(argv[1], "rt")) != NULL) { /* iterate file lines */ #ifdef _WITHGOTO while(fgets(szLine, sizeof(szLine), fStream) != NULL) #else while(fgets(szLine, sizeof(szLine), fStream) != NULL && !nDataErr) #endif { char *ptrToken = strtok(szLine, " "); /* our delim. is (space) character */ /* iterate line numerics */ do{ #ifdef _SSCANF /* with sscanf method (also catch invalid data) */ int nVerify; /* Convert string to int */ if(sscanf(ptrToken, "%d", &nVerify) != 1) /* Verify conversion */ { /* Conversion failed */ printf("*** Invalid data format ***\n"); #ifdef _WITHGOTO goto _Break; /* legal use of "goto" (exit from nested while) */ #else nDataErr = 1; #endif } else printf("%d ", nVerify); #else printf("%d ", atoi(ptrToken)); #endif /* redo until ptrToken empty */ #ifdef _WITHGOTO }while((ptrToken = strtok(NULL, " ")) != NULL); #else }while((ptrToken = strtok(NULL, " ")) != NULL && !nDataErr); #endif /* skip a line to stdout */ printf("\n"); } #ifdef _WITHGOTO _Break: #endif fclose(fStream); } else /* open error! */ printf("Cannot open file for read - %s\n", argv[1]); /* End of program */ printf("Press Enter to exit.."); getchar(); return 0; } Σημείωση: Το _SSCANF define ορίζει στο παραπάνω παράδειγμα ότι θέλουμε να δουλέψει βασιζόμενο στην εναλλακτική μέθοδο sscanf αντί του atoi. Τούτο μπορεί να συμβεί αν θέλουμε να πιάσουμε την ύπαρξη μιας μεμονωμένης ασύμβατης τιμής (πχ. 1 2 3 α) καθώς το atoi σε αυτή την περίπτωση θα επιστρέψει «1 2 3 0». Το _WITHGOTO define ορίζει τον τρόπο με τον οποίο σε περίπτωση ασύμβατης τιμής θα διακόψει το πρόγραμμα την εκτέλεση του. Καθώς είμαστε μέσα σε διπλό loop (while & do { } while) κάποιοι προτιμούν ένα goto (προς _Break;) για έξοδο σε περίπτωση λάθους και κάποιοι άλλοι με την χρήση κάποιου flag (nDataErr == 1). Ο καθένας επιλέγει ότι του αρέσει Υ.Γ. BUFSIZ είναι ένα stdio.h #define το οποίο ορίζει μια μεγάλη τιμή (πχ. 512bytes) ικανή να χωρέσει για παράδειγμα μια συνεχόμενη γραμμή από το αρχείο. Τα #define τα έβαλα διότι μπορεί κάποιος να υπενθυμίσει και την μέθοδο sscanf στο μέλλον, ενώ κάποιος άλλος θα μπορούσε να σοκαριζότανε από το goto κτλ, οπότε είπα να δώσω δυο versions σε ένα source code . Το πρόγραμμα έχει δοκιμασθεί σε ET/CodeGear C/C++ Builder και μπορεί να περιέχει bugs ή άλλες αβλεψίες.
chiossif Δημοσ. 13 Ιουλίου 2009 Δημοσ. 13 Ιουλίου 2009 Θελω να διαβασω μια ακολουθια αριθμων απο ενα αρχειο.Παραδειγμα : 23 129 0 9 576 74 κλπ και μετα να δημιουργησω ενα δυναμικο πινακα. Το προβλημα μου ειναι το πως θα διαβασω τους αριθμους ωστε να αποφευγω τα κενα? Γνωριζω οτι η fscanf δεν μου κανει για αυτη την περιπτωση. Σκεφτομουν να διαβαζω χαρακτηρα χαρακτηρα αλλα εκει πως θα "φτιαχνω" τον αριθμο? Οπως καταλαβαινετε το προβλημα μου δεν ειναι ουτε στο ανοιγμα του αρχειου ουτε στην δημιουργια του πινακα αλλα κυριως στο διαβασμα της ακολουθιας Μπορειτε να με καθοδηγησετε? Γεια και χαρά σε όλους... ΩΡΑΙΑ ΑΣΚΗΣΗ αλλά γιατί την κουτσουρεύετε; Την ξαναγράφω: "Θελω να διαβασω μια ακολουθια αριθμων απο ενα αρχειο.Παραδειγμα : 23 129 0 9 576 74 κλπ και μετα να δημιουργησω ενα δυναμικο πινακα." Και επειδή δεν αποσαφηνίζεται το αρχείο στην νέα αυτή εκφώνηση ας το λύσουμε είτε με αρχείο χαρακτήρων είτε με δυαδικό, άρα δύο διαφορετικά προβλήματα. Απλά τονίζω ότι θα ήθελα η λύση σας να καλύπτει τα ακόλουθα: - δεν είναι από πριν γνωστό το πλήθος των αριθμών ενώ υπάρχει η απαίτηση δυναμικού πίνακα - στο αρχείο χαρακτήρων οι αριθμοί διακρίνονται από οποιοδήποτε κενό (whitespace κατά K&R) χαρακτήρα και - οι αριθμοί στο ψηφιακό αρχείο είναι γνωστού τύπου δηλαδή float ή double (αλήθεια λύνεται χωρίς αυτή την υπόδειξη; ) Δείτε την ως quiz το οποίο θέλει πρώτα απ'όλα βέλτιστη εμφάνιση (εννοώ κατανόηση, κάτι σαν τον κώδικα-"καθρέφτη" που προηγήθηκε) και στην συνέχεια ταχύτητα και οικονομία μνήμης. Επίσης παρακαλώ ας σταθούμε σε ANSI C. (2.0 ή K&R για τους πιστούς...) Καλό καλοκαίρι.
bokarinho Δημοσ. 13 Ιουλίου 2009 Δημοσ. 13 Ιουλίου 2009 Γεια και χαρά σε όλους...ΩΡΑΙΑ ΑΣΚΗΣΗ αλλά γιατί την κουτσουρεύετε; Την ξαναγράφω: "Θελω να διαβασω μια ακολουθια αριθμων απο ενα αρχειο.Παραδειγμα : 23 129 0 9 576 74 κλπ και μετα να δημιουργησω ενα δυναμικο πινακα." Και επειδή δεν αποσαφηνίζεται το αρχείο στην νέα αυτή εκφώνηση ας το λύσουμε είτε με αρχείο χαρακτήρων είτε με δυαδικό, άρα δύο διαφορετικά προβλήματα. Απλά τονίζω ότι θα ήθελα η λύση σας να καλύπτει τα ακόλουθα: - δεν είναι από πριν γνωστό το πλήθος των αριθμών ενώ υπάρχει η απαίτηση δυναμικού πίνακα - στο αρχείο χαρακτήρων οι αριθμοί διακρίνονται από οποιοδήποτε κενό (whitespace κατά K&R) χαρακτήρα και - οι αριθμοί στο ψηφιακό αρχείο είναι γνωστού τύπου δηλαδή float ή double (αλήθεια λύνεται χωρίς αυτή την υπόδειξη; ) Δείτε την ως quiz το οποίο θέλει πρώτα απ'όλα βέλτιστη εμφάνιση (εννοώ κατανόηση, κάτι σαν τον κώδικα-"καθρέφτη" που προηγήθηκε) και στην συνέχεια ταχύτητα και οικονομία μνήμης. Επίσης παρακαλώ ας σταθούμε σε ANSI C. (2.0 ή K&R για τους πιστούς...) Καλό καλοκαίρι. Ο κώδικας του φίλου DirectX ήταν ακριβώς ότι χρειαζόταν για την περίσταση. 'Εκλεψα απροκάλυπτα τον κώδικα και τον τροποποίησα λίγο ώστε να υπάρχει και ο δυναμικός πίνακας που ζήτησε ο φίλος μας. Η όλη φάση γίνεται με την realloc η οποία και κάθε φορά επαυξάνει το μέγεθος του δυναμικού πίνακα όσο τρέχει το loop μας οπότε δεν χρειάζεται ούτε να υπολογίσουμε πόσους αριθμούς έχουμε apriori ούτε τίποτα, πιστεύω ότι με αυτό το πάντρεμα του κώδικα του DirectX(που ελπίζω να μην με μαλώσει που τον πήρα και τον ξαναπόσταρα, ή που μπήκα στην διαδικασία να τον τροποποιήσω)ολοκληρώνεται μία πιθανή εκδοχή λύσης του quiz. Φυσικά μπορεί να υπάρχουν αβλεψίες ή bugs. > /* Read numbers from file with fgets/atoi or sscanf dx */ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <errno.h> /* C preprocessor commands */ #define _SSCANF /* #define _WITHGOTO */ void DumpArray(int *A, int Sz) { int i; for(i = 0, printf("Array Dump:\n"); i < Sz; i++) printf("Array[%d]=%d\n", i, A[i]); } int main(int argc, char* argv[]) { FILE *fStream = NULL; char szLine[bUFSIZ]; int *ptrArray = NULL; static int Index = 0; #ifndef _WITHGOTO int nDataErr = 0; #endif if((fStream = fopen(argv[1], "rt")) != NULL) { /* iterate file lines */ #ifdef _WITHGOTO while(fgets(szLine, sizeof(szLine), fStream) != NULL) #else while(fgets(szLine, sizeof(szLine), fStream) != NULL && !nDataErr) #endif { char *ptrToken = strtok(szLine, " "); /* our delim. is (space) character */ /* iterate line numerics */ do{ #ifdef _SSCANF /* with sscanf method (also catch invalid data) */ int nVerify; /* Convert string to int */ if(sscanf(ptrToken, "%d", &nVerify) != 1) /* Verify conversion */ { /* Conversion failed */ printf("*** Invalid data format ***\n"); #ifdef _WITHGOTO goto _Break; /* legal use of "goto" (exit from nested while) */ #else nDataErr = 1; #endif } else { if(!(ptrArray = realloc(ptrArray, (Index+1)*sizeof(int)))) { perror("Realloc:"); fclose(fStream); return errno; } else ptrArray[index++] = nVerify; } #else printf("%d ", atoi(ptrToken)); #endif /* redo until ptrToken empty */ #ifdef _WITHGOTO }while((ptrToken = strtok(NULL, " ")) != NULL); #else }while((ptrToken = strtok(NULL, " ")) != NULL && !nDataErr); #endif /* skip a line to stdout */ printf("\n"); } #ifdef _WITHGOTO _Break: #endif fclose(fStream); } else /* open error! */ printf("Cannot open file for read - %s\n", argv[1]); DumpArray(ptrArray, Index); /* End of program */ printf("Press Enter to exit.."); getchar(); /* Free Array. */ free(ptrArray); return 0; } **To DirectX: Πραγματικά αυτό το goto απομεινάρι ίσως της assembly είναι τρομακτικό για την C, αλλα ταυτόχρονα πολύ εξυπηρετικό, βέβαια κάποιοι συνιστούν να μην το χρησιμοποιούμε είναι λάθος πρακτική.
Anubis13 Δημοσ. 14 Ιουλίου 2009 Μέλος Δημοσ. 14 Ιουλίου 2009 Ευχαριστω πολυ..Ειχα την εντυπωση οτι θα μπορουσε να γραφτει και πιο απλα αλλα και αυτο κανει την δουλεια του
darksize_ Δημοσ. 17 Ιουλίου 2009 Δημοσ. 17 Ιουλίου 2009 Ευχαριστω πολυ..Ειχα την εντυπωση οτι θα μπορουσε να γραφτει και πιο απλα αλλα και αυτο κανει την δουλεια του γιατί λες πως δε θα δούλευε με την fscanf ? > #include <stdio.h> #include <stdlib.h> int main(){ FILE *fp=fopen("fin.txt","r"); int i,size=6; // ipothetontas pos oi arithmoi einai 6 opos sto paradigma pou dineis int *x; x = (int*)malloc(size*sizeof(int)); if (x==NULL) { printf("fail"); return 1; } else { for (i=1;i<=6;i++){ fscanf(fp,"%d ",&x[i]); printf("%d\n",x[i]); } } free(x); fclose(fp); return 0; }
Προτεινόμενες αναρτήσεις
Αρχειοθετημένο
Αυτό το θέμα έχει αρχειοθετηθεί και είναι κλειστό για περαιτέρω απαντήσεις.