Leuteris Δημοσ. 1 Δεκεμβρίου 2011 Δημοσ. 1 Δεκεμβρίου 2011 Καλησπέρα σας, Έχω ένα δυαδικό αρχείο και μέσο της παρακάτω δομής εχω καταχωρίσει το όνομα και τον βαθμό του κάθε παίκτη.Όταν ο παίκτης δίνει ξανά το όνομα του,το ψάχνω στο αρχείο και του εμφανίζω τους βαθμούς του. Όταν τελειώσει το παιχνίδι οι βαθμοί του θα έχουν αλλάξει. > struct player { char onoma[30]; int vathmos; }; Το πρόβλημα μου είναι: πως θα αλλάξω τους παλιούς βαθμούς που είχε ο παίκτης στο αρχείο με τους καινούργιους? Παράδειγμα ένας νέος παικτης δίνει το όνομα του kostas και στο αρχείο καταχωρήτε το όνομα "kostas" με βαθμούς 0. Όταν τελειώσει το παιχνίδι οι βαθμοί του είναι 25.Πώς μπορώ να κάνω το 0 25; Ευχαριστώ για όποια βοήθεια.
virxen75 Δημοσ. 1 Δεκεμβρίου 2011 Δημοσ. 1 Δεκεμβρίου 2011 και αν έχεις 5 παίκτες με το ίδιο όνομα τι θα κάνεις? ποιο θα αλλάζεις κάθε φορά? μήπως λείπει κάτι από την δομή σου?
defacer Δημοσ. 1 Δεκεμβρίου 2011 Δημοσ. 1 Δεκεμβρίου 2011 Αφού φαντάζομαι ότι γράφεις την αρχική καταχώρηση με fprintf, ο τρόπος να τη διαβάσεις πίσω στη μνήμη (αν δεν το έχεις κάνει ήδη) είναι η fscanf. Απο κει και πέρα, η δουλειά θα γίνει σε κάποιο loop ως εξής: σημειώνεις τον τρέχοντα file pointer με ftell() διαβάζεις record με fscanf αν το record δεν είναι αυτό που ψάχνεις, loop αν είναι, τότε αλλάξεις το score στη μεταβλητή που διάβασε μόλις τώρα η fscanf, κάνεις fseek στην τελευταία τιμή που σημείωσες από την ftell και ξανά fprintf, γράφοντας έτσι την καινούρια τιμή πάνω από την παλιά Φυσικά θα πρέπει να προβλέψεις ότι τα records πρέπει να έχουν μοναδικό όνομα το κάθε ένα, και φυσικά όλο αυτό το σύστημα είναι χάλια προσέγγιση αν το κρίνεις βάσει τεχνικών χαρακτηριστικών. Αλλά είναι καλό σαν πρώτη επαφή για εξάσκηση.
Leuteris Δημοσ. 1 Δεκεμβρίου 2011 Μέλος Δημοσ. 1 Δεκεμβρίου 2011 Αφού φαντάζομαι ότι γράφεις την αρχική καταχώρηση με fprintf, ο τρόπος να τη διαβάσεις πίσω στη μνήμη (αν δεν το έχεις κάνει ήδη) είναι η fscanf. Απο κει και πέρα, η δουλειά θα γίνει σε κάποιο loop ως εξής: σημειώνεις τον τρέχοντα file pointer με ftell() διαβάζεις record με fscanf αν το record δεν είναι αυτό που ψάχνεις, loop αν είναι, τότε αλλάξεις το score στη μεταβλητή που διάβασε μόλις τώρα η fscanf, κάνεις fseek στην τελευταία τιμή που σημείωσες από την ftell και ξανά fprintf, γράφοντας έτσι την καινούρια τιμή πάνω από την παλιά Φυσικά θα πρέπει να προβλέψεις ότι τα records πρέπει να έχουν μοναδικό όνομα το κάθε ένα, και φυσικά όλο αυτό το σύστημα είναι χάλια προσέγγιση αν το κρίνεις βάσει τεχνικών χαρακτηριστικών. Αλλά είναι καλό σαν πρώτη επαφή για εξάσκηση. Ευχαριστώ για την απάντηση θα το κοιτάξω! και ναι εντάξει ακόμα εξάσκηση κάνω.. και αν έχεις 5 παίκτες με το ίδιο όνομα τι θα κάνεις? ποιο θα αλλάζεις κάθε φορά? μήπως λείπει κάτι από την δομή σου? Ναί όντως έχεις δίκιο αυτο όμως θα το ψάξω αργότερα..
migf1 Δημοσ. 1 Δεκεμβρίου 2011 Δημοσ. 1 Δεκεμβρίου 2011 Αν το πλήθος των σκορ είναι περιορισμένο, π.χ. κρατάς μόνο top 5 ή top 10, είναι πολύ πιο εύκολο να ξαναγράφεις όλο το αρχείο από την αρχή κάθε φορά... > int main( void ) { struct player { char onoma[30]; int vathmos; } topscores[ 10 ] = { {"", 0} }; /* top 10 */ ... calc_scores( topscores, ... ); ... FILE *fp = fopen( "scores.dat", "wb"); fwrite( topscores, sizeof(player), 10, fp ); fclose( fp ); ... return 0; } προφανώς με τους κατάλληλους ελέγχους. EDIT: Και για να διαβάζεις το αρχείο στον πίνακα topscores, χρησιμοποιείς την... > fread( topscores, sizeof(player), 10, fp );
nilosgr Δημοσ. 1 Δεκεμβρίου 2011 Δημοσ. 1 Δεκεμβρίου 2011 Διαβαζεις το αρχειο σου με fread() μεχρι να βρεις τον player που θες, κανεις fseek() στην βαθμολογια του και μετα με fwrite() γραφεις την νεα τιμη. Αφού φαντάζομαι ότι γράφεις την αρχική καταχώρηση με fprintf, ο τρόπος να τη διαβάσεις πίσω στη μνήμη (αν δεν το έχεις κάνει ήδη) είναι η fscanf. Σε binary files το IO γινετε με freed() - fwrite() Αν το πλήθος των σκορ είναι περιορισμένο, π.χ. κρατάς μόνο top 5 ή top 10, είναι πολύ πιο εύκολο να ξαναγράφεις όλο το αρχείο από την αρχή κάθε φορά... > int main( void ) { struct player { char onoma[30]; int vathmos; } topscores[ 10 ] = { {"", 0} }; /* top 10 */ ... calc_scores( topscores, ... ); ... FILE *fp = fopen( "scores.dat", "wb"); fwrite( topscores, sizeof(player), 10, fp ); fclose( fp ); ... return 0; } προφανώς με τους κατάλληλους ελέγχους. EDIT: Και για να διαβάζεις το αρχείο στον πίνακα topscores, χρησιμοποιείς την... > fread( topscores, sizeof(player), 10, fp ); πρωτον και κυριο, δεν τον ενδιαφερει το performance και δευτερον τα αρχεια μπορει να τα περνει ετοιμα. οποτε δεν μπορει να κανει υποθεσεις για το μεγεθος τους.
migf1 Δημοσ. 1 Δεκεμβρίου 2011 Δημοσ. 1 Δεκεμβρίου 2011 ... πρωτον και κυριο, δεν τον ενδιαφερει το performance και δευτερον τα αρχεια μπορει να τα περνει ετοιμα. οποτε δεν μπορει να κανει υποθεσεις για το μεγεθος τους Που τα είδες να αναφέρονται αυτά (σίγουρα όχι πάντως από τον ts) ;
παπι Δημοσ. 2 Δεκεμβρίου 2011 Δημοσ. 2 Δεκεμβρίου 2011 φυσικά όλο αυτό το σύστημα είναι χάλια προσέγγιση αν το κρίνεις βάσει τεχνικών χαρακτηριστικών. Αλλά είναι καλό σαν πρώτη επαφή για εξάσκηση. Τι;;; Μια χαρα ειναι Αν θελει κατι παραπανω τοτε 1α) download 1β) download 2) learn 3) Αστους αλλους να ψαχνονται για performance
defacer Δημοσ. 2 Δεκεμβρίου 2011 Δημοσ. 2 Δεκεμβρίου 2011 Τι;;; Μια χαρα ειναι Αν θελει κατι παραπανω τοτε 1α) download 1β) download 2) learn 3) Αστους αλλους να ψαχνονται για performance Ας μη γινόμαστε υπερβολικοί... δε λέω, αν θέλεις να κάνεις σοβαρή δουλειά ένας in-process server του στυλ sqlite είναι πιθανόν η καλύτερη λύση, αλλά αυτό δε σημαίνει ότι δεν έχει νόημα να ψαχτεί κάποιος λίγο παραπάνω. Έτσι ξερά που το θέτεις είναι σα να λες ότι από data structures μόνο το array χρειάζεται να ξέρει κανείς (γιατί ακριβώς γι' αυτό μιλάμε, array serialized σε αρχείο).
Leuteris Δημοσ. 2 Δεκεμβρίου 2011 Μέλος Δημοσ. 2 Δεκεμβρίου 2011 Διαβαζεις το αρχειο σου με fread() μεχρι να βρεις τον player που θες, κανεις fseek() στην βαθμολογια του και μετα με fwrite() γραφεις την νεα τιμη. Αυτές τις συναρτήσεις χρησιμοποιώ: > struct player { char onoma[30]; int vathmos; }players,player1,player2; while(!feof(fp))// μέχρι το τέλος του αρχείου... { fread(&players,sizeof(struct player),1,fp); //καταχωρώ κάθε φορά στην μεταβλητή players το όνομα και τον βαθμό fores++; if(strcmp(player1.onoma,players.onoma)==0)//όταν βρώ το όνομα... { fseek(fp,fores*sizeof(struct player),0);// πηγαίνω στην αρχή του σημείου που θα αλλάξω fwrite(&player1,sizeof(struct player),1,fp); //και γράφω την μεταβλητή player1 στην οποία υπάρχει το όνομα και ο καινούργιος βαθμός break; } } Τι κάνω λάθος;
virxen75 Δημοσ. 2 Δεκεμβρίου 2011 Δημοσ. 2 Δεκεμβρίου 2011 fseek(fp,fores*sizeof(struct player),0);// πηγαίνω στην αρχή του σημείου που θα αλλάξω fwrite(&player1,sizeof(struct player),1,fp); //και γράφω την μεταβλητή player1 στην οποία υπάρχει το όνομα και ο καινούργιος βαθμός για δοκίμασε έτσι > fseek(fp,sizeof(struct player)*(-1),SEEK_CUR); fwrite(&player1,sizeof(struct player),1,fp);
Leuteris Δημοσ. 2 Δεκεμβρίου 2011 Μέλος Δημοσ. 2 Δεκεμβρίου 2011 για δοκίμασε έτσι > fseek(fp,sizeof(struct player)*(-1),SEEK_CUR); fwrite(&player1,sizeof(struct player),1,fp); Δεν δουλεύει.
Erevis Δημοσ. 2 Δεκεμβρίου 2011 Δημοσ. 2 Δεκεμβρίου 2011 Επειδή απ'ότι φαίνεται είσαι καινούργιος στον προγραμματισμό, αν σκοπεύεις να ασχοληθείς σοβαρά με εφαρμογές σε C πρέπει να ξέρεις ότι η fwrite και η fread δεν είναι portable συναρτήσεις. Ο λόγος είναι πως γράφουν τα bytes ακριβώς όπως τα βρίσκουν από τη RAM στο αρχείο κι έτσι όταν πας τα αρχεία/πρόγραμμα σε διαφορετικό σύστημα, το endianess μπορεί να είναι διαφορετικό και να διαβάζεις τα δεδομένα ανάποδα! Επίσης και σε ίδιο endianess να πας μπορεί να υπάρξουν προβλήματα με ta paddings των αρχείων. Οπότε καλύτερα να ξεκινήσεις να τις αποφεύγεις και να χρησιμοποιείς fprintf, fscanf μέχρι να προχωρήσεις σε POSIX.
virxen75 Δημοσ. 2 Δεκεμβρίου 2011 Δημοσ. 2 Δεκεμβρίου 2011 Δεν δουλεύει. δες το και σε πρόγραμμα > #include<stdio.h> #include<stdlib.h> #include <string.h> long currentPlayer=0; struct player{ char onoma[30]; int vathmos; }temp1; void eisagwgh(); void ektupwsh(); void diorthwsh(); int menou(); FILE *fp; int counter=0; int main(){ int epilogi; do{ epilogi=menou(); switch(epilogi){ case 1: eisagwgh(); break; case 2: ektupwsh(); break; case 3: diorthwsh(); break; case 0: printf("exodos:\n"); break; default: printf("error:\n"); break; } }while(epilogi!=0); getchar(); return 0; } //menou epilogwn int menou(){ int ep; printf("\n\nmenou epilogwn:\n"); printf("========================\n"); printf("1.eisagwgh\n"); printf("2.ektupwsh\n"); printf("3.diorthwsh\n"); printf("0.exodos\n"); printf("========================\n"); printf("Dwse epilogh:\n"); scanf("%d",&ep);getchar(); return ep; } //eisagwgh void eisagwgh(){ fp=fopen("players.dat","a+");//α+ ανοίγει το αρχείο για να το συμπληρώσει.Αν δεν το //βρει το δημιουργεί if(fp){//αν υπάρχει το αρχείο τότε fseek(fp,0,SEEK_END);//πήγαινε στο τέλος του } printf("dwse onoma:"); scanf("%s",temp1.onoma);getchar(); printf("dwse vathmo:"); scanf("%d",&temp1.vathmos);getchar(); fwrite(&temp1,sizeof(struct player),1,fp); fclose(fp); } //ektupwsh void ektupwsh(){ fp=fopen("players.dat","r"); if(!fp) printf("To arxeio den uparxei\n"); else{ printf("\nARXEIO PAIKTWN\n"); struct player temp; while(fread(&temp,sizeof(struct player),1,fp)) printf("name=%s vathmos=%d\n",temp.onoma,temp.vathmos); fclose(fp); } } //diorthwsh void diorthwsh(){ int i,N; char onom[30]; printf("dwse onoma\n"); scanf("%s",&onom);getchar(); fp=fopen("players.dat","r+"); if(!fp) printf("den uparxei to arxeio\n"); else{ fseek(fp,0,SEEK_END); N=ftell(fp)/sizeof(struct player);//αριθμός εγγραφών στο αρχείο fseek(fp,0,SEEK_SET); for(i=0;i<N;i++){ fread(&temp1,sizeof(struct player),1,fp); if(strcmp(temp1.onoma,onom)==0){ printf("dwse neo vathmo<%d>:",temp1.vathmos); scanf("%d",&temp1.vathmos);getchar(); fseek(fp,sizeof(struct player)*(-1),SEEK_CUR); fwrite(&temp1,sizeof(struct player),1,fp); break; } } fclose(fp); } }
Leuteris Δημοσ. 2 Δεκεμβρίου 2011 Μέλος Δημοσ. 2 Δεκεμβρίου 2011 virxen75 σε ευχαριστώ για τον χρόνο σου. Το λάθος ήταν πως άνοιγα το αρχείο με "wb" και όχι "r+"
Προτεινόμενες αναρτήσεις
Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε
Πρέπει να είστε μέλος για να αφήσετε σχόλιο
Δημιουργία λογαριασμού
Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!
Δημιουργία νέου λογαριασμούΣύνδεση
Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.
Συνδεθείτε τώρα