Visualizzazione dei risultati da 1 a 7 su 7
  1. #1
    Utente di HTML.it
    Registrato dal
    Apr 2013
    Messaggi
    4

    [C] Scrittura File.. r+b ed fwrite pigro !

    Salve a tutti, primo messaggio sul forum, ma leggo sempre tutti i corsi in home che mi hanno spesse volte dato una mano e insegnato cose nuove
    Vi scrivo principalmente a causa di un problema che mi sta affliggendo da alcuni giorni, uno di quei problemi cosi stupidi e banali che non ti fanno dormire la notte

    A scopo didattico mi è stato assegnato un esercizio per la gestione di una segreteria studenti tramite file ad accesso sequenziale.
    Fin qui tutto ok, non è la prima volta che combatto con i file.
    Il punto è che dopo aver implementato un algoritmo di modifica bello polposo, il tutto non mi funge proprio sul piu bello

    La funzione è la seguente:

    codice:
    void modifica(){
    	studente stud;
    	int i=0,j=0,risp;
    	fp=fopen("PrimoAn.dat","rb");
    	char tmp[10];
    	if(fp!=NULL){
    		printf("Inserisci il cognome dello studente che vuoi modificare: ");
    		scanf("%s",tmp);
    		printf("Elementi corrispondenti:\n\n");
    		fread(&stud,sizeof(studente),1,fp);
    		while(!feof(fp)){
    			if(strcmp(tmp,stud.cognome)==0){
    				printf("%d %s %s %s %s %d %s\n\n",stud.codice,stud.cognome,stud.nome,stud.voto,stud.lang,stud.classe,stud.sez);
    				printf("Vuoi modificare questo elemento? 0=no 1=si\n");
    				scanf("%d",&risp);
    				if(risp==1){
    					fclose(fp);
    					fp=fopen("PrimoAn.dat","r+b");
    					while(j<i){
    						fread(&stud,sizeof(studente),1,fp);
    						j++;
    					}
    					j=0;
    					printf("Inserisci i dati dello studente separati da uno spazio:\n");
    					printf("<Codice> <Cognome> <Nome> <Voto diploma> <Lingua> <Classe> <Sezione>\n");
    					scanf("%d %s %s %s %s %d %s",&stud.codice,&stud.cognome,&stud.nome,&stud.voto,&stud.lang,&stud.classe,&stud.sez);
    					fwrite(&stud,sizeof(studente),1,fp);
    				}
    			}
    			fread(&stud,sizeof(studente),1,fp);
    			i++;
    		}
    		fclose(fp);
    	}
    	else{
    		printf("Archivio vuoto\n");
    	}
    }
    Il codice sorgente completo lo potete trovare qui:

    https://dl.dropboxusercontent.com/u/...ria_studenti.c

    Ho debuggato il programma con decine di break point e sono arrivato alla conclusione che tutto cicla e procede come dovrebbe, il buffer prende i giusti valori prima della scrittura e il puntatore al file punta esattamente dove dovrebbe.
    L'inghippo purtroppo scatta nell' fwrite che trovate poco prima della fine dell'if, che in pratica sembra rifiutarsi di scrivere su file il buffer stud appena scaneffato ..
    Il punto sapete qual è ?
    Che questo stesso identico codice sorgente, compilato ed eseguito su c4droid (compilatore c per android per chi non lo sapesse) GIRA A MERAVIGLIA
    Il file viene correttamente scritto ed il record risulta perfettamente modificato alla visualizzazione successiva.
    Su PC ho provato sia con Visual C++ che con DevC , ed il risultato è sempre il medesimo..
    fwrite in alcun modo vuol fare il proprio dovere.

    Qualche anima pia può illuminarmi prima che faccia in 1000 pezzi compilatore, notebook, cellulare android e libretto universitario?

  2. #2
    Utente di HTML.it
    Registrato dal
    Apr 2013
    Messaggi
    4
    Noone? :/

  3. #3
    Il problema l' ho avuto pure io usando DevC. Quando apri un file in "r+b" in teoria sui libri si studia che si può sia leggere e scrivere su file. Bhe con devC non funziona così. Se una volta aperto il file cominci con un fwrite potrai solo usare fwrite e viceversa con fread. io ho risolto usando un file d' appoggio, copiandogli quello che c' era nell' altro file, lavorare sul file d' appoggio poi alla fine rimuovere il file vecchio e rinominare il file d' appoggio con il nome del file vecchio.

    Questa è una funzione in cui ho usato questo metodo. remove e rename sono funzioni del sistema operativo quindi non è detto che funzioni su tutti i sistemi. io a scuola e a casa ho windows e probabilmente ce l' hai anche tu. te lo dico caso mai ci fosse quella rara eventualità
    codice:
    void modifica_tutti(stringa nome){
        FILE *temp,*f;
        stringa city;
        int box,pos;
        f=fopen(nome,"rb");
        temp=fopen("temp.txt","wb");
        if(f!=NULL){
                    while(fread(city,sizeof(stringa),1,f)!=0){
                                                              fread(&box,sizeof(int),1,f); 
                                                              pos+=(pos*10)/100;
                                                              fwrite(city,sizeof(stringa),1,temp);
                                                              fwrite(&pos,sizeof(int),1,temp);
                                                              }
                    fclose(f);
                    fclose(temp);
                    remove(nome);
                    rename("temp.txt",nome);
                    }      
    }

    Spero di esserti stato d' aiuto
    Haters gonna hate

  4. #4
    Utente di HTML.it L'avatar di oregon
    Registrato dal
    Jul 2005
    residenza
    Roma
    Messaggi
    36,480
    Originariamente inviato da Automatik
    Quando apri un file in "r+b" in teoria sui libri ... si studia ...
    In realtà basta leggere la documentazione per capire come funzionano i file aperti in r+ ...

    La documentazione della funzione fseek riporta

    "On streams open for update (read+write), a call to fseek allows to switch between reading and writing."

    Quindi, quando devi passare da una fwrite ad una fread e viceversa, inserisci una fseek (anche se questa non sposta il puntatore).
    No MP tecnici (non rispondo nemmeno!), usa il forum.

  5. #5
    Utente di HTML.it
    Registrato dal
    Apr 2013
    Messaggi
    4
    Originariamente inviato da Automatik
    Il problema l' ho avuto pure io usando DevC. Quando apri un file in "r+b" in teoria sui libri si studia che si può sia leggere e scrivere su file. Bhe con devC non funziona così. Se una volta aperto il file cominci con un fwrite potrai solo usare fwrite e viceversa con fread. io ho risolto usando un file d' appoggio, copiandogli quello che c' era nell' altro file, lavorare sul file d' appoggio poi alla fine rimuovere il file vecchio e rinominare il file d' appoggio con il nome del file vecchio.

    Questa è una funzione in cui ho usato questo metodo. remove e rename sono funzioni del sistema operativo quindi non è detto che funzioni su tutti i sistemi. io a scuola e a casa ho windows e probabilmente ce l' hai anche tu. te lo dico caso mai ci fosse quella rara eventualità
    codice:
    void modifica_tutti(stringa nome){
        FILE *temp,*f;
        stringa city;
        int box,pos;
        f=fopen(nome,"rb");
        temp=fopen("temp.txt","wb");
        if(f!=NULL){
                    while(fread(city,sizeof(stringa),1,f)!=0){
                                                              fread(&box,sizeof(int),1,f); 
                                                              pos+=(pos*10)/100;
                                                              fwrite(city,sizeof(stringa),1,temp);
                                                              fwrite(&pos,sizeof(int),1,temp);
                                                              }
                    fclose(f);
                    fclose(temp);
                    remove(nome);
                    rename("temp.txt",nome);
                    }      
    }

    Spero di esserti stato d' aiuto
    TI ringrazio molto per il suggerimento, ma purtroppo dovevo seguire le indicazioni del prof, che sulle slide ha esplicitamente indicato un algoritmo come il mio .
    Anche io personalmente avrei usato un file temporaneo, soluzione meno contorta e molto piu facilmente applicabile, ma tant'è ...
    Grazie cmq

    Originariamente inviato da oregon
    In realtà basta leggere la documentazione per capire come funzionano i file aperti in r+ ...

    La documentazione della funzione fseek riporta

    "On streams open for update (read+write), a call to fseek allows to switch between reading and writing."

    Quindi, quando devi passare da una fwrite ad una fread e viceversa, inserisci una fseek (anche se questa non sposta il puntatore).
    Eh l'ho scoperto stanotte leggendo una mail del prof
    Il punto sai qual è ?
    Che questa cosa la si può leggere nella documentazione dell'fseek, ma effettivamente, partendo da un approccio sequenziale e considerando fseek una istruzione tipicamente utilizzata dall'accesso diretto, diventa difficile capire dove si trova l'errore senza qualcuno che te lo spieghi
    Associa anche il fatto che questa cosa non è esposta in maniera chiara e limpida quando vengono introdotte le varie modalità di apertura, cosa che invece si dovrebbe evidenziare immediatamente ..



    Senti adesso la domanda sorge spontanea..
    Se apro in r+b ..
    Leggo ...
    Fseek ...
    Scrivo ...
    Poi posso passare nuovamente in modalità lettura con un altro fseek o devo necessariamente chiudere e riaprire il file?

    Grazie mille per l'aiuto

  6. #6
    Utente di HTML.it L'avatar di oregon
    Registrato dal
    Jul 2005
    residenza
    Roma
    Messaggi
    36,480
    Il punto sai qual è ?
    Sì, ammetto che l'individuazione di questo particolarità della modalità r+ è un po' difficile ...
    La cosa però è facilitata dal fatto che con la modalità binaria e la fread/fwrite, prima o poi ti capita di fare una fseek e allora scopri tutto ...

    Poi posso passare nuovamente in modalità lettura
    Sì, basta una fseek per cambiare da r/w e da w/r
    No MP tecnici (non rispondo nemmeno!), usa il forum.

  7. #7
    Utente di HTML.it
    Registrato dal
    Apr 2013
    Messaggi
    4
    Grandissimo
    Piu tardi posto un programmino di gestione di una segreteria, si sa mai dovesse servire a qualcuno

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.