simplfuzz
simplfuzz

Reputation: 12895

C++ file handling (structures)

Following code, when compiled and run with g++, prints '1' twice, whereas I expect '1' to be printed only once, since I am dumping a single structure to the file, but while reading back it seems to be reading two structures. Why?

#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();
}

Upvotes: 2

Views: 1016

Answers (5)

simplfuzz
simplfuzz

Reputation: 12895

Cool. Another way (courtesy of experts-exchange, I asked the same question there :-))

while(filin.peek() != EOF)
{
    filin.read((char*)&tmpStu,sizeof(tmpStu));
    cout << tmpStu.rollNo << endl;
}

Upvotes: 0

Eclipse
Eclipse

Reputation: 45493

eof only gets set after a read fails, so the read runs twice, and the second time, it doesn't modify the buffer.

Try this:

while(filin.read((char*)&tmpStu,sizeof(tmpStu)))
{
    cout << tmpStu.rollNo << endl; 
}

Or

while(!filin.read((char*)&tmpStu,sizeof(tmpStu)).eof())
{
    cout << tmpStu.rollNo << endl; 
}

Read returns a reference to filin when called, which will evaluate to true if the stream is still good. When read fails to read any more data, the reference will evaluate to false, which will prevent it from entering the loop.

Upvotes: 11

Jay Conrod
Jay Conrod

Reputation: 29681

This prints 1 twice because of the exact way eof and read work. If you are at the very end of a file, read will fail, then calls to eof after that return true. If you have not attempted to read past the end of the file, eof will return false because the stream is not in the EOF state, even though there is no more data left to read.

To summarize, your calls look like this:

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)

A better strategy would be to check eof right after the read call.

Upvotes: 2

borq
borq

Reputation: 681

I believe it is because you are checking for filin.eof() and that won't be true until the second time you read.

See here. It notes that eofbit is set "...The end of the source of characters is reached before n characters have been read ...". In your case you won't hit EOF until the second read.

Upvotes: 1

Steve Fallows
Steve Fallows

Reputation: 6424

Your while loop is executing twice because the EOF condition is not true until the first attempt to read beyond the end of the file. So the cout is executed twice.

Upvotes: 5

Related Questions