Utilizzo feof()

di il
12 risposte

Utilizzo feof()

Ciao a tutti, qualcuno sa dirmi perchè, in questo semplice programma, il ciclo while stampa due volte lo stesso testo (il quale ha meno di 2000 caratteri)?
Cioè, in teoria dovrebbe leggere il testo una volta e poi il puntatore dovrebbe stare sull'EOF e quindi il ciclo non dovrebbe essere eseguito.
Oppure ammesso che il puntatore al file non sia ancora posizionato sull'EOF, il while verrebbe eseguito ma quando viene eseguita l'istruzione fgets() dovrebbe leggere "il nulla" e quindi non stampare niente.
Invece stampa due volte lo stesso testo.
In effetti anche leggendo (per esempio) 50 caratteri per volta, il ciclo viene sempre eseguito due volte sugli stessi ultimi caratteri.
Inoltre, questo problema non me lo da se eseguo il programma su un altro compilatore come questo (online) https://www.onlinegdb.com/online_c_compile
Per inciso, il testo contenuto nel file è Lorem Ipsum Standard di Wikipedia (https://it.wikipedia.org/wiki/Lorem_ipsu)


int main(int argc, char **argv)
{
	FILE *file;
	char text[1000];
	
	file = fopen("text.txt", "r");
	
	while(!feof(file)) {
	
		fgets(text, 2000, file);
		printf("Puntatore: %p\n%s\n\n", file, text);
	
	}
	
	fclose(file);
	
	return 0;
}

12 Risposte

  • Re: Utilizzo feof()

    Prova con un "do".
  • Re: Utilizzo feof()

    Ma come 'prova'?
  • Re: Utilizzo feof()

    Riprendo il tuo codice, senza cambiare altro che l'uso di "do" anziché di "while":
    int main(int argc, char **argv)
    {
       FILE *file;
       char text[1000];
       
       file = fopen("text.txt", "r");
       
       do {
       
          fgets(text, 2000, file);
          printf("Puntatore: %p\n%s\n\n", file, text);
       
       } while(!feof(file));
       
       fclose(file);
       
       return 0;
    }
  • Re: Utilizzo feof()

    AldoBaldo ha scritto:


    Prova con un "do".
    Sicuramente qualche modo c'è per farlo funzionare, ma vorrei capire il perchè succede questo.
    Comunque con il do{}while(); stesso identico problema. Ripeto questo avviene sul mio pc e non se compilo il programma online.
    Sarà il compilatore
  • Re: Utilizzo feof()

    "Prova" nel senso che cambi quel poco, poi provi a vedere se funziona e ragioni sul come e sul perché...
  • Re: Utilizzo feof()

    Ad esempio, io ho provato e mi sono accorto che "do" o non "do" non cambia nulla. Funziona, invece, facendo così:
    while(fgets(text, 2000, file)) {
        printf("Puntatore: %p\n%s\n\n", file, text);
    }
    Da quel che ho capito succede perché fgets() restituisce il puntatore al buffer text ogni volta che porta a termine il suo compito con successo, e NULL quando non riesce a portarlo a termine. Dunque, quel while accede al suo blocco di codice solo quando effettivamente è stato letto qualcosa dal file, e lo salta se la lettura non è stata possibile. Essere all'eof è una delle condizioni per le quali la lettura è impossibile.

    Oh, poi io mica sono un esperto!
  • Re: Utilizzo feof()

    Grazie mille!
  • Re: Utilizzo feof()

    AldoBaldo ha scritto:


    ... succede perché ...
    Succede perché la condizione di superamento della fine del file viene impostata DOPO che la fgets l'ha superato.

    Quindi, quando viene letto l'ultima riga la feof non si accorge dell'eof e la fgets viene eseguita un'altra volta. A questo punto la feof può accorgersi del superamento della fine del file.

    Se usi la do, dai per scontato che il file contenga almeno una riga e non va bene se il file è vuoto.

    A parte la soluzione del non usare feof ma direttamente fgets, si dovrebbe scrivere

    fgets ...
    while( !feof )
    { fgets ... }

    Nel caso specifico
    
    	fgets(text, 2000, file);
    	while (!feof(file)) {
    		printf("Puntatore: %p\n%s\n\n", file, text);
    		fgets(text, 2000, file);
    	}
    
  • Re: Utilizzo feof()

    Grazie per la risposta Oregon ma non credo dipenda da quello.
    Dato che nel mio caso l'ultima riga veniva letta due volte,credo che con il tuo codice avverrebbe lo stesso problema.
    Nel caso in cui il file ha più di una riga, tra i due codici (il tuo e quello che ho postato io all'inizio) non cambierebbe nulla perchè tanto l'ultima riga verrebbe "incontrata" nel while, producendo lo stesso errore.
    Nel caso in cui il file abbia una sola riga, secondo me il problema di presenterebbe ancora.

    Tuttavia non posso neanche dare alcuna prova perchè, per assurdo, adesso il programma (copiato e incollato dal mio primo post che apre l'argomento), non mi dà più alcun problema. Strano, non so perchè ma ora lo stesso codice non legge due volte l'ultima riga.
  • Re: Utilizzo feof()

    Simki98 ha scritto:


    Grazie per la risposta Oregon ma non credo dipenda da quello.
    Parli per esperienza, la stessa esperienza che mi ha portato a risponderti? Da quanto usi il C? Da 30+ anni?
    Dato che nel mio caso l'ultima riga veniva letta due volte,credo che con il tuo codice avverrebbe lo stesso problema.
    Ti ho spiegato quale è la causa e il rimedio del "tuo caso", ma tu "credi" senza aver fatto neanche una prova (e penso anche senza avere letto la documentazione della funzione feof).
    Nel caso in cui ...
    Va beh ... lasciamo perdere.
  • Re: Utilizzo feof()

    Nono, in realtà prove ne ho fatte. Ho riprovato sia il mio codice che il tuo ma come ti ripeto la cosa strana è che il problema non avviene più neanche con il vecchio codice e per questo non so dirti.
    Comunque sia come tu stesso hai sottolineato io ho scritto "credo" (dopo aver provato) per i motivi scritti sopra e perchè appunto non ho nessuna pretesa di avere ragione e non vorrei tu avessi interpretato la mia risposta come tale.
  • Re: Utilizzo feof()

    Probabilmente adesso hai inserito una linea vuota alla fine del file di testo e quindi non ti accorgi che la linea vuota viene letta due volte.
Devi accedere o registrarti per scrivere nel forum
12 risposte