2

I have this text sample

Ahmed 10
kmal 5
doola 6

And I am using this code to read it

if (myfile.is_open())
{
  while ( myfile.good() )
{

    myfile >> name;
    myfile >> phone;
    cout << name <<" "<<phone<<endl;

}
myfile.close();

}

I get this output

Ahmed 10
kmal 5
doola 6
doola 6

Why does this code read the last line twice ?

Ahmed
  • 3,398
  • 12
  • 45
  • 64

4 Answers4

6

myfile.good() becomes false AFTER the read fails. Same with myfile.eof().

What you want is basically:

myfile >> name;
myfile >> phone;
if (!myfile.good()) break;

And this can be shortened to:

if (!(myfile >> name >> phone)) break;

or finally:

while (myfile >> name >> phone) { ... }
Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
2

Try

while( myfile >> name >> phone ) {
    // your code here
}

I believe the problem with the other approach is that eof isn't signaled until you actually try to read more than you should. That is, when you attempt to myfile >> name on the last round. That fails, as does myfile >> phone and only then do you break out of the loop.

Pablo
  • 8,644
  • 2
  • 39
  • 29
1

Don't use while(myfile.good()). It will still say true, even when you have read the last line in your file. And then the next >> will fail, leaving the name and phone variables unchanged from the last input. Use this instead: while(myfile >> name >> phone) {...}

Xeo
  • 129,499
  • 52
  • 291
  • 397
  • @Ahmed: Ché, I forgot that the same problem exists with `eof()`, sorry. :) Try the new version. – Xeo Mar 29 '11 at 01:39
1

iostream status is not predictive. It reports the results of the previous operation, not of the next (which would be impossible to implement anyway). And myfile.good() isn't even a reliable indicator of the results of the previous operation: if the operation failed, it will be false, but if the operation succeeded, it's not necessarily true. Forget that function.

Use the fact that the stream can act as a boolean to test success of the previous operation. Once you have failure, you can then use eof(), and bad() to determine why (but with regards to eof(), only after failure---eof() may return true even if the previous operation succeeded). Thus:

while ( myfile >> name >> phone ) {
    //  ...
}
if ( myfile.bad() ) {
    std::cerr << "Hardware read error" << std::endl;
} else if ( !myfile.eof() ) {
    std::cerr << "Format error in file" << std::endl;
}
James Kanze
  • 150,581
  • 18
  • 184
  • 329