Oltre alla fine del file, esistono altri errori possibili quando si cerca di leggere da file. Alcuni errori sono dovuti per esempio a problemi di livello hardware, altri a livello di sistema operativo, ecc. Di questo tipo di errori non ci interessiamo.
Un errore di cui invece parliamo è il fallimento di conversione. Quando si cerca di leggere da file un intero, la funzione fscanf deve convertire una stringa in intero. Infatti, un file di testo è una sequenza di caratteri, ossia una stringa. Se vogliamo un intero, dobbiamo convertire i caratteri che si trovano su file in un intero.
Questa conversione non è sempre possibile. Si pensi per esempio alla situazione in cui su file sono memorizzati i caratteri abe mds. Questa sequenza non corrisponde a nessun intero. Se si cerca di leggere un intero, deve essere possibile capire che la conversione da stringa a intero è fallita.
Errori di questo genere si riflettono sul valore di ritorno della funzione fscanf. Questa funzione, in generale, può leggere più di un oggetto per volta. Per esempio, può leggere, con una chiamata sola, un intero, una stringa, e un reale. Il valore di ritorno della funzione è il numero di oggetti che sono è stato possibile convertire. Il valore EOF viene ritornato solo nel caso in cui si è incontrata la fine del file prima ancora di riuscire a convertire anche un solo intero.
la funzione fscanf ritorna il numero di oggetti che è stato possibile leggere (convertire da stringa al tipo dell'oggetto), oppure EOF se il file è finito prima di poter leggere il primo oggetto.
Esempio:
fscanf(fd, "%d %d", &x, &y); ha i seguenti possibili valori di ritorno:
Si noti che, se il risultato è 1, allora non è possibile capire se il problema è stato un errore di conversione oppure la fine del file. Per il momento, questo fatto non ci interessa, visto che leggiamo sempre un unico elemento per volta. Nel caso in cui la fscanf viene usata per leggere da file il valore di una sola variabile, allora i possibili valori di ritorno sono:
fscanf(fd, "%d", &x);
Da questa schema è chiaro che, nel caso di lettura di un solo intero, è sempre possibile capire quale errore si è verificato semplicemente guardando il valore di ritorno della funzione fscanf.
Il programma arrayerr.c è l'ultima versione del programma di lettura di un array da file. Questa volta è stato aggiunto un controllo sulla lettura: se la conversione in intero è fallita allora la funzione fscanf ritorna il valore 0, e in questo caso il programma termina.
/* Legge un array da file fino all'eof. Salta le cose che non riesce a leggere. */ #include<stdlib.h> #include<stdio.h> int main() { int n; int vett[100]; FILE *fd; int res; int i; /* apre il file */ fd=fopen("arrayerr.txt", "r"); /* verifica errori in apertura */ if( fd==NULL ) { perror("Errore in apertura del file"); exit(1); } /* legge l'array */ for(n=0; n<=99; n++) { res=fscanf(fd, "%d", &vett[n]); if( res==EOF ) break; else if( res==0 ) { printf("Non riesco a leggere un intero da file\n"); exit(1); } } /* stampa l'array */ for(i=0; i<=n-1; i++) printf("%d\n", vett[i]); /* chiude il file */ fclose(fd); return 0; }
Nel caso in cui non interessa stabilire quale particolare errore si è verificato, basta controllare che il valore di ritorno della funzione fscanf coincida con il numero di elementi che doveva leggere (in questo caso, uno), e generare un messaggio di errore in caso contrario.