Gestione dei file C ++ (strutture)
Domanda
Il codice seguente, quando compilato ed eseguito con g ++, stampa "1" due volte, mentre mi aspetto che venga stampato "1" solo una volta, dal momento che sto scaricando un'unica struttura a il file, ma durante la lettura sembra essere leggere due strutture. Perché?
#include <iostream.h>
#include <fstream.h>
int main(){
struct student
{
int rollNo;
};
struct student stud1;
stud1.rollNo = 1;
ofstream fout;
fout.open("stu1.dat");
fout.write((char*)&stud1,sizeof(stud1));
fout.close();
ifstream filin("stu1.dat");
struct student tmpStu;
while(!filin.eof())
{
filin.read((char*)&tmpStu,sizeof(tmpStu));
cout << tmpStu.rollNo << endl;
}
filin.close();
}
Soluzione
eof
viene impostato solo dopo una lettura non riuscita, quindi la lettura viene eseguita due volte e la seconda volta non modifica il buffer.
Prova questo:
while(filin.read((char*)&tmpStu,sizeof(tmpStu)))
{
cout << tmpStu.rollNo << endl;
}
O
while(!filin.read((char*)&tmpStu,sizeof(tmpStu)).eof())
{
cout << tmpStu.rollNo << endl;
}
Leggi restituisce un riferimento a filin quando viene chiamato, che valuterà vero se lo stream è ancora buono. Quando read non riesce a leggere altri dati, il riferimento verrà valutato come falso, impedendogli di entrare nel ciclo.
Altri suggerimenti
Il ciclo while viene eseguito due volte perché la condizione EOF non è vera fino al primo tentativo di leggere oltre la fine del file. Quindi il cout viene eseguito due volte.
Stampa 1 due volte a causa del modo esatto in cui funzionano eof
e read
. Se sei alla fine di un file, read
fallirà, quindi le chiamate a eof
dopo che torneranno vere. Se non hai tentato di leggere oltre la fine del file, eof
restituirà false perché il flusso non è nello stato EOF, anche se non ci sono più dati da leggere.
Per riassumere, le tue chiamate sono così:
eof - false (at beginning of file)
read (at beginning of file)
eof - false (now at end of file, but EOF not set)
read (at end of file. fails and sets EOF state internally)
eof - true (EOF state set)
Una strategia migliore sarebbe quella di controllare eof
subito dopo la chiamata read
.
Credo che sia perché stai controllando filin.eof () e questo non sarà vero fino alla seconda lettura.
Vedi qui . Nota che è impostato eofbit " ... La fine della fonte di caratteri viene raggiunta prima che n caratteri siano stati letti ... " ;. Nel tuo caso non colpirai EOF fino alla seconda lettura.
Cool. Un altro modo (per gentile concessione dello scambio di esperti, ho fatto la stessa domanda lì :-))
while(filin.peek() != EOF)
{
filin.read((char*)&tmpStu,sizeof(tmpStu));
cout << tmpStu.rollNo << endl;
}