Salta ai contenuti. | Salta alla navigazione

Strumenti personali

fread

importante

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 della fread, 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 della fread 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 di fread, siamo gia` alla fine del file, quindi e` inutile fare il controllo su feof. Le sconsiglio poi di usare feof 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:

  1. Effettua un ciclo in cui controlla il valore restituito dalla fread. Nella fread legge 1 solo valore (e non 30): se la fread 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++;
    }
  2. Chiede alla fread di leggere 30 elementi, ed esegue la fread 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' del while 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).