xpapias Δημοσ. 21 Δεκεμβρίου 2006 Δημοσ. 21 Δεκεμβρίου 2006 Έχω ένα αρχείο με ονόματα. Θέτω ένα array από strings και προσπαθώ σε καθένα από τα strings του να δίνω μια τιμή από αυτές που διαβάζω από το αρχείο. Δηλ. γράφω στη main: char *a[100]; int i=0; FILE *fl = fopen ("arxeio","r"); while (fscanf(fl,"%s ",a) !=EOF) i++; fclose (fl); Το πρόγραμμα γίνεται compile χωρίς σφάλματα, όμως όταν το τρέχω προκύπτει μήνυμα λάθους. Όταν αντί για a στην fscanf ΄βαλω ένα άλλο string (που το έχω δηλώσει πχ ως char t[20]) το πρόγραμμα δουλεύει κανονικά. Τι κάνω λάθος;
chiossif Δημοσ. 21 Δεκεμβρίου 2006 Δημοσ. 21 Δεκεμβρίου 2006 Διότι το char *a[100] δηλώνει ένα πίνακα 100 δεικτών σε χαρακτήρα ενώ το char t[20] δηλώνει ένα πίνακα 20 χαρακτήρων. Αποφάσισε: 1η διάσταση Πόσα string έχεις και 2η διάσταση Πόσους χαρακτήρες θα βάζεις. Μετά... μετά εδώ είμαστε...
xpapias Δημοσ. 21 Δεκεμβρίου 2006 Μέλος Δημοσ. 21 Δεκεμβρίου 2006 Διότι το char *a[100] δηλώνει ένα πίνακα 100 δεικτών σε χαρακτήρα ενώ το char t[20] δηλώνει ένα πίνακα 20 χαρακτήρων.Αποφάσισε: 1η διάσταση Πόσα string έχεις και 2η διάσταση Πόσους χαρακτήρες θα βάζεις. Μετά... μετά εδώ είμαστε... Μισό.. Θέλω να αποθηκεύω ονόματα. Άν δηλώσω char *a[100] και μετά a[1]="Peter", a[2]="George" κλπ, μου δουλεύει κανονικά. Για ποιό λόγο δε μπορώ να βάλω το a στο fscanf; Δηλ. άν πω ότι θέλω να έχω ένα πίνακα 20 strings με 50 χαρακτήρες το καθένα, πως το δηλώνω;
parsifal Δημοσ. 21 Δεκεμβρίου 2006 Δημοσ. 21 Δεκεμβρίου 2006 Αν ως ανώτατο όριο για το κάθε string που θα διαβάζεται θεωρείς έστω x χαρακτήρες, ο πίνακας a αρκεί να δηλωθεί ώς: >char a[100][x+1]; Αν τώρα θες να το κάνεις πιο τυπικά, θα πρέπει ο a να είναι πίνακας δεικτών σε πίνακα χαρακτήρων, να έχεις έναν αρκούντως μεγάλο buffer όπου θα αποθηκεύεις προσωρινά το κάθε string για να μετρήσεις το μήκος του, και μετά να δεσμεύεις δυναμικά την απαιτούμενη μνήμη για να τοποθετήσεις το κάθε string... ***Edit: Ουπς, sorry παιδιά που μπήκε σαν σφήνα, βλέπω είχατε ξεκινήσει να το συζητάτε!
chiossif Δημοσ. 21 Δεκεμβρίου 2006 Δημοσ. 21 Δεκεμβρίου 2006 Η πρόταση a[1]="Peter"; αν έχει προηγηθεί η δήλωση char *a[100]; είναι σωστή διότι στην ήδη κατειλημένη μνήμη "Peter" δείχνει ο δείκτης a[1]. Αν γράψω scanf("%s",a[1]); που να βάλει η κακομοίρα η scanf τα data; Θα πρέπει να έχει γίνει είτε κάτι σαν αυτό char a[20][50] ή κάτι με malloc -είναι νωρίς ακόμα-. Ποιό βιβλίο διαβάζεις; Έχεις το http://cm.bell-labs.com/cm/cs/cbook/ ; No problem parsifal. Άλλωστε για μένα είναι ώρα για ύπνο...
Directx Δημοσ. 22 Δεκεμβρίου 2006 Δημοσ. 22 Δεκεμβρίου 2006 Αν και δεν χρησιμοποιώ την fscanf για τέτοιου είδους δουλείες (τώρα μάλλον θα αλλάξω γνώμη ) στην παρούσα περίπτωση σχεδίασα τον παρακάτω κώδικα ο οποίος διαβάζει 100 ονόματα ή μέχρι το EOF από ένα αρχείο κειμένου με την προϋπόθεση πως κάθε όνομα έχει μήκος ως 12 χαρακτήρες σε διαφορετική περίπτωση το πρόγραμμα σταματά -μεταξύ μας δύσκολα θα βρεις όνομα (όχι επώνυμο) στην Ελλάδα τόσο μεγάλο . Κάθε όνομα αποθηκεύεται σε έναν buffer των 14 ωφέλιμων χαρακτήρων ο οποίος αργότερα μικραίνει στο πραγματικό μέγεθος του ονόματος για εξοικονόμηση μνήμης (ομολογώ πως μου άρεσε η ιδέα του Parsifal). Ο κώδικας έχει γραφθεί σε CodeGear Turbo C++ Express και έχει δοκιμασθεί με input stream των 23 ονομάτων - φυσικά μπορεί να περιέχει Bugs. > //--------------------------------------------------------------------------- #include <stdio.h> #include <stdlib.h> #include <string.h> #include <conio.h> //--------------------------------------------------------------------------- #define MAX_NAME_LIST 100 FILE *Stream = NULL; int nArrayIdx; char *pszArray[MAX_NAME_LIST]; int main(int argc, char* argv[]) { if((Stream=fopen(argv[1],"r"))!=NULL) { memset(pszArray,0,sizeof(char)*MAX_NAME_LIST); for(nArrayIdx=0;nArrayIdx<MAX_NAME_LIST;nArrayIdx++) { if((pszArray[nArrayIdx]=malloc(15))==NULL) { printf(" Out of memory!\n"); break; } memset(pszArray[nArrayIdx],0,sizeof(unsigned char)*15); if(fscanf(Stream,"%14s",pszArray[nArrayIdx])==EOF) break; if(strlen(pszArray[nArrayIdx])>=13) { printf(" Name on line or delimeter #%d very long - %.12s ..!\n", nArrayIdx,pszArray[nArrayIdx]); break; } printf(" %d\n",strlen(pszArray[nArrayIdx])); if((pszArray[nArrayIdx]=realloc(pszArray[nArrayIdx], (size_t)strlen(pszArray[nArrayIdx])+1))==NULL) { printf(" Memory reallocation failure!\n"); break; } printf(" pszArray[%.2d] = %s (Actual Length:%d)\n", nArrayIdx,pszArray[nArrayIdx],strlen(pszArray[nArrayIdx])); } fclose(Stream); for(nArrayIdx=0;nArrayIdx<MAX_NAME_LIST;nArrayIdx++) if(!pszArray[nArrayIdx]) break; else free(pszArray[nArrayIdx]); } else printf(" Cannot open file for read - %s\n",argv[1]); printf(" HIT ANY KEY TO QUIT ..."); getch(); return 0; } //--------------------------------------------------------------------------- Υ.Γ. Άραγε μπορεί να σχεδιασθεί αποδοτικός κώδικας ώστε να αίρεται ο φυσικός περιορισμός στο μέγεθος του ονόματος με την χρήση της fscanf (να μην θέτουμε περιορισμό στο μέγεθος της ονομασίας).
xpapias Δημοσ. 22 Δεκεμβρίου 2006 Μέλος Δημοσ. 22 Δεκεμβρίου 2006 Σας ευχαριστώ και τους 3 για τις απαντήσεις, και ειδικά τον directX που έκατσε και έφτιαξε και κώδικα. Βιβλίο έχω ήδη των Kernighan και Richie. Θα κοιτάξω τον κώδικα του directX και θα διαβάσω και από το βιβλίο. Απ'οτι κατάλαβα χωρίς memory allocation δεν γίνονται και πολλά γενικά...
Προτεινόμενες αναρτήσεις
Αρχειοθετημένο
Αυτό το θέμα έχει αρχειοθετηθεί και είναι κλειστό για περαιτέρω απαντήσεις.