Giorgos3924 Δημοσ. 11 Ιουλίου 2010 Δημοσ. 11 Ιουλίου 2010 Καλησπέρα! Έχω ένα πρόβλημα σε εγγραφή και ανάγνωση δεδομένων σε αρχείο με τη C. Έχω μια δομή struct που περιέχει 10 πίνακες τύπου char. η μεταβλητή του struct είναι επίσης πίνακας. Έτσι έχω έναν πίνακα 10 θέσεων πχ, που περιέχει ετικέτες με κάποια στοιχεία. Τα οποία θέλω να περάσω στο αρχείο. Το πρόβλημα είναι ότι καθώς τυπώνω τα στοιχεία στο αρχείο ξεχωρίζοντας τα με "#" ανάμεσα σε κάποια από αυτά δεν τυπώνεται η "#" και εμφανίζονται ενωμένα. Δηλαδή Αντί να εμφανιστούν ως: >1# electronica # thesaloniki # 342415134 # 6900000000 # 12.33 # 12/02/2003 # 150E Εμφανίζονται έτσι: >1# electronica # thesaloniki # 342415134 # 690000000012.3312/02/2003150E # 12.3312/02/2003150E # 12/02/2003150E # 150E Ο κώδικας του προγράμματος είναι μια χαρά. > fp=fopen("book.txt","w"); fprintf(fp,"%d# ", x+1); fputs(book[x].eteria,fp); fprintf(fp," # "); fputs(book[x].address,fp); fprintf(fp," # "); fputs(book[x].afm,fp); fprintf(fp," # "); fputs(book[x].thl,fp); fprintf(fp," # "); fputs(book[x].time,fp); fprintf(fp," # "); fputs(book[x].hmerominia,fp); fprintf(fp," # "); fputs(book[x].timi,fp); fclose(fp); Μετά στην ανάγνωση με ποιόν τρόπο θα μπορούσα να πάρω τα στοιχεία πίσω;
_tasos Δημοσ. 11 Ιουλίου 2010 Δημοσ. 11 Ιουλίου 2010 Αν και οι γνώσεις μου στη C είναι λίγο σκουριασμένες... Οι 10 πίνακες τύπου char έχουν συγκεκριμένο μέγεθος; Αν ναι, θα πρέπει να βάλεις +1 στο μέγεθος τους για να συμπεριλάβεις κ τον χαρακτήρα /0 που δηλώνει το τέλος του string. Δηλαδή για το τηλέφωνο που είναι 10ψήφιο θα πρέπει να το αποθηκεύεις σε πίνακα χωρητικότητας 10+1=11 θέσεων. Χωρίς αυτό όταν προσπαθεις να τυπώσεις το τηλέφωνο, τυπώνονται τα πάντα μέχρι να βρει το /0 ή να πάρεις segmentation fault.
Giorgos3924 Δημοσ. 11 Ιουλίου 2010 Μέλος Δημοσ. 11 Ιουλίου 2010 Αν και οι γνώσεις μου στη C είναι λίγο σκουριασμένες... Οι 10 πίνακες τύπου char έχουν συγκεκριμένο μέγεθος; Αν ναι, θα πρέπει να βάλεις +1 στο μέγεθος τους για να συμπεριλάβεις κ τον χαρακτήρα /0 που δηλώνει το τέλος του string. Δηλαδή για το τηλέφωνο που είναι 10ψήφιο θα πρέπει να το αποθηκεύεις σε πίνακα χωρητικότητας 10+1=11 θέσεων. Χωρίς αυτό όταν προσπαθεις να τυπώσεις το τηλέφωνο, τυπώνονται τα πάντα μέχρι να βρει το /0 ή να πάρεις segmentation fault. Ναι αυτό ήταν! Ευχαριστώ πολύ για την παρατήρηση. Είχα ξεχάσει το /0 ---------- Προσθήκη στις 23:56 ---------- Προηγούμενο μήνυμα στις 23:46 ---------- Επίσης συνάντησα μία ακόμα ιδιοτροπία. Ακόμα πιο περίεργο. Το πρόγραμμα αυτό το έβγαλα από τη main και το έβαλα σε μία συνάρτηση void χωρίς παραμέτρους και χωρίς να επιστρέφει τίποτα. Απλά θα παίρνει στοιχεία από το πληκτρολόγιο και θα τα περνάει στο αρχείο. Στη main έχω μια switch Όταν δοθεί κάποια σταθερά στη switch θα εκτελεστεί η συνάρτηση. Μόνο τότε. Όταν όμως εκτελείται την ώρα που ζητάει όνομα εταιρίας και διεύθυνση τα ζητάει ταυτόχρονα. δηλαδή με λίγα λόγια παρακάμπτει τη μία gets που έχω για ανάγνωση χαρακτήρων από το πληκτρολόγιο. και στην οθόνη μου βγάζει: >dose onoma etairias: ([color="Blue"]εδώ χάνουμε τη μια gets[/color]) dose dieuthinsi: ([color="blue"]εδώ περιμένει πληκτρολόγηση[/color]) Η συνάρτηση δουλεύει κανονικά εκτός της switch. Δηλαδή αν την βάλω κάπου αλλού στο πρόγραμμα θα δουλέψει κανονικά. Μόνο στη switch μέσα είδα αυτό το πρόβλημα.
thanos713 Δημοσ. 11 Ιουλίου 2010 Δημοσ. 11 Ιουλίου 2010 Kάνε πριν από την πρώτη gets() ένα fflush(stdin)...
Giorgos3924 Δημοσ. 12 Ιουλίου 2010 Μέλος Δημοσ. 12 Ιουλίου 2010 Kάνε πριν από την πρώτη gets() ένα fflush(stdin)... Καλύτερα τώρα. Τί κάνει αυτό;
thanos713 Δημοσ. 12 Ιουλίου 2010 Δημοσ. 12 Ιουλίου 2010 Αδειάζει όσους χαρακτήρες έχουν μείνει στο πληκτρολόγιο...
Giorgos3924 Δημοσ. 12 Ιουλίου 2010 Μέλος Δημοσ. 12 Ιουλίου 2010 Αδειάζει όσους χαρακτήρες έχουν μείνει στο πληκτρολόγιο... Δηλαδή επηρεαζόταν από την επιλογή της switch;
_tasos Δημοσ. 12 Ιουλίου 2010 Δημοσ. 12 Ιουλίου 2010 Η σταθερά για τη switch την δίνεις από το πληκτρολόγιο; Με ποιά εντολή; Μάλλον δεν καταναλώνεται το '\n' που δίνεις για αυτή τη σταθερά κ το καταναλώνει η 1η gets.
Giorgos3924 Δημοσ. 12 Ιουλίου 2010 Μέλος Δημοσ. 12 Ιουλίου 2010 Τώρα το αντίθετο πώς θα μπορούσε να γίνει; Να πάρω τα στοιχεία από το αρχείο και να τα αποθηκεύσω στα structs. Το πρόβλημα είναι οτι θα πρέπει να έχω πολλές τέτοιες σειρές με στοιχεία. Σκέφτηκα νa ξεχωρίζω τους πίνακες με #, και κάθε φορά που βλέπει # να αλλάζει κάποιον δείκτη και να πηγαίνει στο επόμενο πίνακα του struct. Σταματάει όταν τελειώσει η γραμμή. ---------- Προσθήκη στις 00:26 ---------- Προηγούμενο μήνυμα στις 00:24 ---------- Η σταθερά για τη switch την δίνεις από το πληκτρολόγιο; Με ποιά εντολή; Μάλλον δεν καταναλώνεται το '\n' που δίνεις για αυτή τη σταθερά κ το καταναλώνει η 1η gets. Ναι από το πληκτρολόγιο με scanf... τύπου int
_tasos Δημοσ. 12 Ιουλίου 2010 Δημοσ. 12 Ιουλίου 2010 Καλή ιδέα, κάθε γραμμή θα είναι ένα struct και κάθε γραμμή θα την κάνεις split με το # για να πάρεις τον κάθε πίνακα.
Giorgos3924 Δημοσ. 12 Ιουλίου 2010 Μέλος Δημοσ. 12 Ιουλίου 2010 Καλή ιδέα, κάθε γραμμή θα είναι ένα struct και κάθε γραμμή θα την κάνεις split με το # για να πάρεις τον κάθε πίνακα. Διαπιστώνω ένα πρόβλημα όπως στην αλλαγή των structs. Το πως από έναν πίνακα θα μεταβεί στον επόμενο όταν βλέπει #.
Evgenios1 Δημοσ. 12 Ιουλίου 2010 Δημοσ. 12 Ιουλίου 2010 @Giorgos3924 Εφοσον εχεις strcut με γνωστο μεγεθος, γιατι δε το γραφεις οπος ειναι; δες ενα παραδειγμα (ειναι c++ αλλα με c style) >#pragma pack(1) struct foo { char a[10]; char b[10]; char c[10]; }; int _tmain(int argc, _TCHAR* argv[]) { FILE *fp =fopen("test","wb"); foo f; strcpy(f.a,"abcd"); strcpy(f.b,"1234"); strcpy(f.c,"!@$%"); fwrite(&f,sizeof(foo),1,fp); fclose(fp); fp = fopen("test","rb"); foo f1; fread(&f1,sizeof(foo),1,fp); printf("%s\n%s\n%s",f1.a,f1.b,f1.c); fclose(fp); getchar(); return 0; }
3c0r1z Δημοσ. 12 Ιουλίου 2010 Δημοσ. 12 Ιουλίου 2010 Kάνε πριν από την πρώτη gets() ένα fflush(stdin)... Βασικά καλό είναι να αποφεύγεται η χρήση της fflush(stdin). int fflush(FILE *ostream); ostream points to an output stream or an update stream in which the most recent operation was not input, the fflush function causes any unwritten data for that stream to be delivered to the host environment to be written to the file; otherwise, the behavior is undefined. http://faq.cprogramming.com/cgi-bin/smartfaq.cgi?answer=1052863818&id=1043284351 Μια πιθανή λύση είναι η εξής: >int c; while ((c = getchar()) != EOF && c != '\n') ;
Giorgos3924 Δημοσ. 12 Ιουλίου 2010 Μέλος Δημοσ. 12 Ιουλίου 2010 Εγώ το σκεφτόμουν αλλιώς. Στο αρχείο: >electronica # thesaloniki # 342415134 # 6900000000 # 12.33 # 12/02/2003 # 150E Ξεκινάμε με: >[color="blue"]do {[/color] [color="Green"]ch=fgetc(fp);[/color] [color="Red"]if (ch!='#') metabliti[0].eteria[i]=ch;[/color] [color="blue"] i++;}[/color] [color="Blue"]while (ch!='#');[/color] Μετά από εδώ θα πρέπει να αλλάζει το 2ο μέλος του strutct. Το πρόβλημα είναι πως θα αλλάζει για να πάμε στη δεύτερη λέξη και να τη καταχωρήσουμε στο 2ο πίνακα.
Evgenios1 Δημοσ. 12 Ιουλίου 2010 Δημοσ. 12 Ιουλίου 2010 Πρεπει οπωσδηποτε να κανεις parse απο αυτο το format;
Προτεινόμενες αναρτήσεις
Αρχειοθετημένο
Αυτό το θέμα έχει αρχειοθετηθεί και είναι κλειστό για περαιτέρω απαντήσεις.