Come funziona ifof di estream ()?

#include  #include  int main() { std::fstream inf( "ex.txt", std::ios::in ); while( !inf.eof() ) { std::cout << inf.get() <> c ) { std::cout << c << "\n"; } return 0; } 

Sono davvero confuso sulla funzione eof() . Supponiamo che il contenuto del mio ex.txt sia:

 abc 

Legge sempre un carattere extra e mostra -1 durante la lettura usando eof() . Ma l’ inf >> c dato l’output corretto che era ‘abc’? Qualcuno può aiutarmi a spiegare questo?

    -1 è il modo per dire che hai raggiunto la fine del file. Confrontalo usando lo std::char_traits::eof() (o std::istream::traits_type::eof() ) – evita -1, è un numero magico. (Anche se l’altro è un po ‘prolisso – puoi sempre chiamare istream::eof )

    Il flag EOF viene impostato solo quando una lettura tenta di leggere oltre la fine del file . Se ho un file di 3 byte e leggo solo 3 byte, EOF è false , perché non ho ancora provato a leggere oltre la fine del file. Mentre questo sembra confondere i file, che in genere conoscono le loro dimensioni, EOF non è noto fino a quando non viene tentata una lettura su alcuni dispositivi, come pipe e socket di rete.

    Il secondo esempio funziona come inf >> foo restituirà sempre inf , con l’effetto collaterale di tentare di leggere qualcosa e di memorizzarlo in foo . inf , in un if o while , valuterà in true se il file è “buono”: nessun errore, nessun EOF. Pertanto, quando una lettura fallisce, inf evaula su false e il tuo loop si interrompe correttamente. Tuttavia, prendi questo errore comune:

     while(!inf.eof()) // EOF is false here { inf >> x; // read fails, EOF becomes true, x is not set // use x // we use x, despite our read failing. } 

    Tuttavia, questo:

     while(inf >> x) // Attempt read into x, return false if it fails { // will only be entered if read succeeded. } 

    Che è quello che vogliamo

    iostream non sa che è alla fine del file fino a quando non tenta di leggere quel primo carattere oltre la fine del file.

    Il codice di esempio su cplusplus.com dice di farlo in questo modo: (ma non dovresti farlo in questo modo)

      while (is.good()) // loop while extraction from file is possible { c = is.get(); // get character from file if (is.good()) cout < < c; } 

    Un idioma migliore è quello di spostare la lettura nella condizione di loop, in questo modo: (Puoi farlo con tutte le operazioni di lettura di istream che restituiscono *this , incluso l'operatore >> )

      char c; while(is.get(c)) cout < < c; 

    Il flag EOF viene impostato solo dopo un’operazione di lettura che tenta di leggere oltre la fine del file. get() sta restituendo i traits::eof() costanti simbolici traits::eof() (che capita esattamente uguale a -1) perché ha raggiunto la fine del file e non è stato in grado di leggere altri dati, e solo a quel punto sarà eof() vero . Se vuoi verificare questa condizione, puoi fare qualcosa di simile al seguente:

     int ch; while ((ch = inf.get()) != EOF) { std::cout < < static_cast(ch) < < "\n"; } 

    eof () controlla l’eofbit nello stato del stream.

    In ogni operazione di lettura, se la posizione è alla fine del stream e devono essere letti più dati, eofbit è impostato su true. Quindi otterrai un carattere extra prima di ottenere eofbit = 1.

    Il modo corretto consiste nel verificare se è stato raggiunto l’eof (o se l’operazione di lettura è riuscita) dopo l’operazione di lettura. Questo è ciò che fa la seconda versione: si esegue un’operazione di lettura e quindi si utilizza il riferimento dell’object di stream risultante (che >> restituisce) come valore booleano, che risulta in controllo di fail ().