kostas111 Δημοσ. 9 Ιουνίου 2006 Δημοσ. 9 Ιουνίου 2006 Γειά σας, όπως γράφω και στο τίτλο θέλω να γράψω και να διαβάζω δυαδικά αρχεία. γράφω 3 τύπους μεταβλητών px int i=10; double j=10.4; char str[80]="lala"; se 80 bytes xwro to kathena: fwrite(&i,80,1,fp); klpklp (swstos den einai o tropos?) Το ερώτημα από δω και πέρα είναι πώς μπορώ να διαβάσω το αρχείο 80 80 bytes ΧΩΡΙΣ να ξέρω τι τυπου είναι οι μεταβλητές και μετά να τις κάνω cast? πχ fread(...(ti typou vazw edw?) , 80, 1 ,fp) και μετά αν γνωρίζω οτι το 1 είναι int πως το κανω cast? πχ αν βάλω fread(&h , 80, 1 ,fp) (h ti na einai?) printf("%d",h); douleuei etsi? please κάποια βοήθεια!!! ευχαριστώ!
Επισκέπτης Δημοσ. 9 Ιουνίου 2006 Δημοσ. 9 Ιουνίου 2006 mporeis poly apla na afhseis kena anamesa sta dedomena px 10 10.4 lala 20 32.4 tralala 45 34.34 alatralala meta einai eykolo na to diabaseis ana 3.. 9a soy apanthsw plhrestera to apogeyma..
kostas111 Δημοσ. 9 Ιουνίου 2006 Μέλος Δημοσ. 9 Ιουνίου 2006 nai alla auta pou grafeis den einai diadika arxeia.. egw thelw diadika arxeia... kai ama koitakseis ta kena yparxoun. px o int poianei 1-2 bytes.. kai egw touy dinw 80...
alkisg Δημοσ. 9 Ιουνίου 2006 Δημοσ. 9 Ιουνίου 2006 Δεν έχει νόημα να γράφεις 80 byte για έναν int. Ο int συνήθως έχει μέγεθος 4, ενώ για τη γενική περίπτωση χρησιμοποιείς sizeof. H fwrite(&i,80,1,fp) θεωρείται λάθος, αφού γράφει και οτιδήποτε junk υπάρχει στη RAM μετά τα 4 byte του i, οπότε αν θες ντε και καλά να γράφεις 80 byte γράψε με ξεχωριστή εντολή τα 4 του int και με μία ακόμα άλλα 76 από ένα null-αρχικοποιημένο string. Για να δεις από το αρχείο τι τύπος είναι αυτό που έγραψες δεν υπάρχει τρόπος. Θα πρέπει να προσθέσεις εξτρά πληροφορία, π.χ. ένα ακόμα byte ΠΡΙΝ τα δεδομένα, όπου: αν είναι 0, ακολουθεί int αν είναι 1, ακολουθεί string μήκους 80 κτλ κτλ
kostas111 Δημοσ. 9 Ιουνίου 2006 Μέλος Δημοσ. 9 Ιουνίου 2006 xm... katalava... ayto pou les ginetai alla thelei polla if else... alla as poume oti exw ena arxeio me dodomena.. prepei na to anoiksw gia na dw ti einai kai na ta apothikeuw sth mnhmh se ena pinaka i se mia domh klp pws tha ginei na arxikopoihsw ton pinaka? ti tha einai?einai vlakeia na anoigw 500 pinakes gia to skopo auto... giauto elega mhpws yparxei kati geniko... i kati pou na einai panw apo ola kai meta na ginei to cast.. kamia idea?
Legionnaire Δημοσ. 9 Ιουνίου 2006 Δημοσ. 9 Ιουνίου 2006 Υπάρχουν δυο προσεγγίσεις: α) γράφεις χύμα μέσα στο αρχείο και μετά, αν ξέρεις ότι π.χ. έχεις πρώτα έναν int, μετά έναν char, κλπ διαβάζεις τα 4 πρώτα byte, τα κάνεις cast, ύστερα το επόμενο byte, το κάνεις cast, κλπ β) να κάνεις pad κάθε μεταβλητή που γράφεις στην μνήμη. Δηλαδή αν έχεις έναν int να γράφεις τα 4 byte του int και στην συνέχεια άλλα 76 μηδενικά. Έτσι το αρχείο σου έχει block των 80 byte. Αυτό είναι μεν ασφαλές αλλά αρκετά χαζό καθώς σπαταλάς αρκετή μνήμη και φυσικά περιορίζεις τα string σου σε 80 bytes. Γενικά όταν περιορίζεις τις μεταβλητές σου σε μέγιστες τιμές το πρόγραμμα σου "χάνει" σε ευχρηστία. Καλύτερα να δουλεύεις με arbitrary δεδομένα (όπως π.χ. στην περίπτωση (α)). γ) μια τρίτη λύση (που ουσιαστικά επεκτείνει την (α)) είναι να γράφεις ακριβώς όσα byte έχεις (όχι 80 δηλαδή) και πριν από κάθε καταχώρηση να δηλώσεις πόσα byte θα γράψεις. Π.χ. το αρχείο σου θα είναι: > '4'0010'1'A για μια μεταβλητή int (αριθμός 10) και μια char (γράμμα 'Α'). Όπως βλέπεις με 'x' όπου x τα byte που ακολουθούν μπορείς να οργανώσεις το φορμά το αρχείου σου με αρκετά efficient τρόπο. Επίσης συμφωνώ με τον alkis για την fread/fwrite.
kostas111 Δημοσ. 10 Ιουνίου 2006 Μέλος Δημοσ. 10 Ιουνίου 2006 ok.. kala ola auta alla den einai to provlhma mou pws tha ta grapsw.. prepei gia orismenous logous na ta grapsw se orismena bytes ta dedomena mou. Auto ok kai ta grafw... to pws ta diavazw genika kai pws kanw to programma moy geniko na ta apothikeuei sth mnhmh? dhladiti kai an kserw sth mesh toy programmatos oti to arxeio exei int mesa?afou prepei na anoiksw 500 pinakes apo prin? Pws mporw na ta apothikeusw aneksarthtws eidous dedomenwn... mia idea as poume (pou psilodouleuei) einai na ta grafw ola se double( int,float,char ginontai double...) kai meta diavazw ola se double ta apothikeuw.. kai an thelw peretairw ta kanw cast.. auto exei to arnitiko tou polu megalou xwrou pou xreiazomai... yparxei san kai auth allh idea?
Sta Δημοσ. 10 Ιουνίου 2006 Δημοσ. 10 Ιουνίου 2006 Όπως είπαν και οι προλαλήσαντες, πρέπει να καταγράφεις με κάποιο τρόπο τον τύπο μεταβλητών που αποθηκεύεις. Το ερώτημα είναι για ποιο λόγο θέλεις να κάνεις αυτό που λες. Το ρωτάω διότι τέτοιοι χειρισμοί ενέχουν και πολλούς κινδύνους για έναν άπειρο προγραμματιστή. Π.χ. το casting είναι επικίνδυνο και δεν το συνιστώ (λόγω alignment requirements κ.τλ.). Το πιο σωστό είναι να παίξεις με πίνακα unsigned char[] και να ρίχνεις εκεί τα bytes των μεταβλητών ένα-ένα, χρήσιμη (και ασφαλής) θα σου φανεί η συνάρτηση memcpy.
kostas111 Δημοσ. 10 Ιουνίου 2006 Μέλος Δημοσ. 10 Ιουνίου 2006 Αυτό που θέλω να κάνω το είπα πριν... είναι ένα δυναμικό πρόγραμμα που να διαβάζει δυαδικά αρχεία και να τα κρατάει στη μνήμη. ανα 5 πεδία οι τύποι είναι οι ίδιοι(τα συνολικά πεδία μπορεί να είναι παρα πολλά).Όμως πως θα ορίσω τη δομή που θα κρατάει τα 5 πεδία? Φαντάσου πόσες δομές πρέπει να ορίσω παίζοντας με τους τύπους int float double kai string..... Αυτό είναι το πρόβλημα και έχω κολλήσει 2 μέρες...
alkisg Δημοσ. 10 Ιουνίου 2006 Δημοσ. 10 Ιουνίου 2006 Κοίτα, τα αρχεία μπορεί να είναι δυαδικά, αλλά το να έχεις "δυαδική πληροφορία" στη μνήμη που να την κάνεις cast κάθε τρεις και λίγο δεν είναι καλή μέθοδος. Εξήγησε λίγο περισσότερο αυτό που θες να κάνεις, γιατί έχω τη διαίσθηση ότι θα υπάρχει ευκολότερος τρόπος χωρίς casting. Π.χ. το τελευταίο "ανά 5 πεδία οι τύποι είναι οι ίδιοι" δεν το κατάλαβα, αλλά αν εννοείς ότι θες να αποθηκεύεις πληροφορίες του στυλ "Όνομα Επώνυμο Ηλικία Διεύθυνση Ημερομηνία γέννησης" κτλ, τότε η καταλληλότερη δομή είναι μια λίστα από structs (τα οποία τα γράφεις με μία fwrite σε binary αρχεία). Επίσης, υπάρχουν διάφορες τεχνολογίες (variants, streamable objects) με τις οποίες δε χρειάζεται casting. Αν τελικά χρειάζεσαι casting, τότε το σε τι μεταβλητές θα τα αποθηκεύεις στη μνήμη δεν παίζει ρόλο. Το double δεν κάνει γιατί έχει μέγεθος 8 byte (συνήθως) και δεν χωράει strings. Είτε λοιπόν βάζεις unsigned char[...] είτε void pointers, και κάνεις malloc όσα byte θέλεις. Εξήγησε πολύ πιο αναλυτικά αυτό που θες να κάνεις, νομίζω ότι έτσι θα γλυτώσεις πολύ κόπο.
kostas111 Δημοσ. 10 Ιουνίου 2006 Μέλος Δημοσ. 10 Ιουνίου 2006 Ναι, είναι μια βάση δεδομένων με 5 πεδία. πχ "Όνομα Επώνυμο Ηλικία Διεύθυνση Ημερομηνία γέννησης" αλλά κάποιος άλλος το γράφει "Διεύθυνση Όνομα Ηλικία Επώνυμο Ημερομηνία γέννησης" (εννοείται οτι υπάρχει κάπου η πληροφορία για το πως είναι γραμμένα) Το πρόβλημά μου είναι αυτό που λες να ορίσω τη δομή. Τι πεδία θα έχει μέσα? Το double χωράει χαρακτήρες και όχι string φυσικά... για χαρακτήρες μιλούσα. Το unsigned char παλι δεν βολεύει γιατί δεν χωράει double(έτσι δεν είναι?)? Θα ήθελα να μου εξηγήσεις λίγο για τους void pointers ή ότι άλλο σκεφτόσουνα! Ευχαριστώ!!
kostas111 Δημοσ. 10 Ιουνίου 2006 Μέλος Δημοσ. 10 Ιουνίου 2006 μην δέσεις κόμπο αυτά τα πεδία: "Όνομα Επώνυμο Ηλικία Διεύθυνση Ημερομηνία γέννησης" το πρόγραμμα πρέπει να μπορεί να διαβάζει "κάθε" βάση με 5 πεδία. "όλες" τις δυνατές διατάξεις των int double string float
Sta Δημοσ. 10 Ιουνίου 2006 Δημοσ. 10 Ιουνίου 2006 Ως ενδιάμεσο χώρο αποθήκευσης μπορείς να θεωρήσεις ένα πίνακα: > unsigned char data[size]; ,όπου size είναι το μέγεθος σε bytes της δομής που χρησιμοποιείς (που είναι ίδιο για όλες τις εκδοχές των δομών). Έπειτα ανάλογα και με τη σειρά των πεδίων στη δομή μπορείς να εξάγεις από τον παραπάνω πίνακα τα bytes που αντιστοιχούν σε κάθε πεδίο. Πιο συγκεκριμένα, μπορείς να αντιστοιχίσεις σε κάθε δομή τη θέση κάθε πεδίου μέσα στον προηγούμενο πίνακα. Δηλαδή, αν η σειρά είναι "Όνομα Επώνυμο Ηλικία Διεύθυνση Ημερομηνία γέννησης" έχεις (1,2,3,4,5), αν είναι "Διεύθυνση Όνομα Ηλικία Επώνυμο Ημερομηνία γέννησης" έχεις (2,4,3,1,5) κ.ο.κ. Από την προηγούμενη αντιστοίχιση φτιάχνεις τα offsets κάθε πεδίου μέσα στον πίνακα ανάλογα και με το μέγεθος κάθε τύπου δεδομένων. Είδα μόλις ότι στη δεύτερη απάντησή σου γενικεύεις το πρόβλημα. Δίνεις 4 τύπους δεδομένων ενώ μιλάς για "βάση" με 5 πεδία. Αυτό σημαίνει ότι κάποιο από τα πεδία που αναφέρεις επαναλαμβάνεται; Εκεί νομίζω δυσκολεύουν λίγο παραπάνω τα πράγματα μιάς και κάθε "βάση" μπορεί να καταλαμβάνει διαφορετική ποσότητα μνήμης.
kostas111 Δημοσ. 10 Ιουνίου 2006 Μέλος Δημοσ. 10 Ιουνίου 2006 poly endiaferon ayto pou les... dhladh na diavazw ena ena bytes me unsigned char. etsi den mporw na kanw mia domh me 5 unsigned char kai na apothikeuw ta pedia oti kai na einai auta? Meta kai otan tha thelw na kanw kati i na ta typwsw sthn othoni ta kanw cast.. etsi den einai?
Sta Δημοσ. 10 Ιουνίου 2006 Δημοσ. 10 Ιουνίου 2006 Πρέπει να έχεις ένα πίνακα unsigned char[] με τέτοιο μέγεθος ώστε να επαρκεί για τη δομή που διαβάζεις. Ας πούμε αν διαβάζεις μία δομή που περιέχει: int, double και char *, πρέπει να έχεις πίνακα με μέγεθος: sizeof(int) + sizeof(double) + sizeof(char*), που (στο σύστημά μου) είναι: 4 + 8 + 4 = 16. Οπότε, εγώ θα όριζα: > unsigned char data[16]; ή σεβόμενος τη γενικότητα: > unsigned char data[sizeof(int)+sizeof(double)+sizeof(char *)]; Χρησιμοποιώντας τη συνάρτηση fread μπορείς να διαβάζεις κάθε φορά 8 bytes από το αρχείο και να τα αποθηκεύεις στον προηγούμενο πίνακα. Έπειτα, με διάφορους τρόπους μπορείς να πάρεις τα επιμέρους δεδομένα που θέλεις, αλλά όπως είπα και παραπάνω το cast είναι επικίνδυνο. Π.χ. αν η σειρά αποθήκευσης είναι (double,int, char*) μπορείς να κάνεις το εξής: > double d; int i; char *c; memcpy(&d,data,sizeof(double)); memcpy(&i,data+sizeof(double),sizeof(int)); memcpy(&c,data+sizeof(double)+sizeof(int),sizeof(char *)); Ένα ολοκληρωμένο πρόγραμμα που δείχνει τον τρόπο που σκέφτομαι είναι το εξής, με τη διαφορά ότι δεν έχω διαβάσει από αρχείο: > #include <stdio.h> #include <string.h> int main(void) { double d = 1.12; int i=19; char a[] = "this is a test"; char *c = a; unsigned char data[sizeof(double)+sizeof(int)+sizeof(char *)]; memcpy(data,&d,sizeof(double)); memcpy(data+sizeof(double),&i,sizeof(int)); memcpy(data+sizeof(double)+sizeof(int),&c,sizeof(char *)); memcpy(&d,data,sizeof(double)); memcpy(&i,data+sizeof(double),sizeof(int)); memcpy(&c,data+sizeof(double)+sizeof(int),sizeof(char *)); printf("d= %f, i= %d, s= %s\n",d,i,c); return 0; } Μπορείς βέβαια να γενικεύσεις φτάνοντας σε ένα πιο κομψό αποτέλεσμα.
Προτεινόμενες αναρτήσεις
Αρχειοθετημένο
Αυτό το θέμα έχει αρχειοθετηθεί και είναι κλειστό για περαιτέρω απαντήσεις.