fread
con la presente sono a chiederle una delucidazione riguardante il valore restituiro dalla funzione fread(). In particolare il mio problema riguarda la visualizzazione dei dati letti da tale funzione dal file PAZIENTI.BIN, fornito nel compito del 13 marzo 2006.
Il mio listato è il seguente:
//PROVO A LEGGERE IL FILE BINARIO pazienti.bin DEL COMPITO DEL 13 MARZO 2006
// E A STAMPARE A VIDEO IL CONTENUTO.
#include<stdio.h>
#include<stdlib.h>
#define DIM 30
//DEFINISCO LA STRUTTURA
struct dati
{ char cognome[20];
int priorita;
int giorno;
}
main()
{
FILE *fp;
int i,n;
struct dati pazienti[DIM];
fp=fopen("pazienti.bin","rb");
if (fp==NULL)
{ fprintf(stderr,"**\tERRORE APERTURA FILE\t**\n");
exit(1);
}
while (!feof(fp))
{ for (i=0;i<DIM;i++)
n=fread(pazienti,sizeof(struct dati),DIM,fp);
}
fclose(fp);
//STAMPO A VIDEO IL CONTENUTO DEL FILE
for (i=0;i<n;i++) //SECONDO CICLO for
printf("I DATI SONO: %s %d %d\n",pazienti[i].cognome, pazienti[i].priorita, pazienti[i].giorno);
}
Il mio problema riguarda la visualizzazione del file a video, in particolare se nel secondo ciclo for al posto di n sostituisco DIM, mi compaiono dati non leggibili (in quanto il ciclo legge dati non presenti nel file), invece se metto la variabile n (che assume il numero di elementi letti dalla fread()), a video non compare nulla.
Non capisco dove sia l'errore.
Mi sembra che la visualizzazione sia corretta, ma la lettura e`
sbagliata. La fread
cerca di leggere DIM (30) dati, ma, come detto nel
testo, i dati sono meno di 30: sono 25. Quindi la prima volta che viene
eseguita fread
, n=25. A questo punto il ciclo for
incrementa il valore
di i (i varra` 1) e viene effettuata una nuova lettura. Visto che non
ci sono piu` elementi nel file, fread
non leggera` niente e restituira`
0. Si continua cosi` per 30 volte a fare delle letture a vuoto:
all'uscita del for
, n varra` quindi 0.
A questo punto viene testata la condizione del while
: siamo alla fine del file, quindi si esce subito dal ciclo.
La stampa, a questo punto, stampa correttamente n=0 elementi.
Si possono osservare le seguenti cose:
- e` inutile effettuare 30 volte la
fread
. Infatti sappiamo dal testo che nel file ci sono meno di 30 elementi, mentre il suo programma cerca di leggerne 30 in ogni esecuzione dellafread
, quindi 30x30=900. Inoltre, in ogni successiva lettura, cerca di mettere gli elementi letti all'inizio dell'array; quindi se anche ci fossero piu` di 30 elementi, nella seconda esecuzione dellafread
i nuovi elementi sovrascriverebbero quelli letti in precedenza. - Anche il
while
e` inutile: dopo che ha letto tutti gli elementi del file con la prima esecuzione difread
, siamo gia` alla fine del file, quindi e` inutile fare il controllo sufeof
. Le sconsiglio poi di usarefeof
con i file binari, perche' a volte dà dei risultati sbagliati: lo usi solo con i file di testo.
Per effettuare la lettura correttamente, puo` fare in due modi:
- Effettua un ciclo in cui controlla il valore restituito
dalla
fread
. Nellafread
legge 1 solo valore (e non 30): se lafread
precedente ha restituito 1 vuol dire che il file non e` finito, altrimenti vuol dire che siamo ad end of file.int letto=1, n=0;
...
while (letto)
{
letto=fread(pazienti,sizeof(struct dati),1,fp);
n++;
} - Chiede alla
fread
di leggere 30 elementi, ed esegue lafread
solo 1 volta (senza cicli):n=fread(pazienti,sizeof(struct dati),DIM,fp);
E` sufficiente questa istruzione per effettuare la lettura: non c'e` bisogno ne' del ciclo
for
, ne' delwhile
che ha messo lei.
Provi ad eseguire passo-passo le due versioni del programma con il debugger (sia quella che ha fatto lei, sia una di quelle corrette) e guardi il valore assunto dalle variabili (in particolare, n).