2

I have a question about the ifstream::operator>> behavior in the following code:

#include <iostream>
#include <string>
#include <fstream>
using namespace std;

int main () {
    ifstream inFile("test.txt");
    string buffer;
    while (!inFile.eof()) {
        inFile >> buffer;
        cout << buffer << endl;
    }
    return 0;
}

This code works perfectly well if the last line of test.txt is not empty, for instance :

One two
Three four
Five six

However if test.txt is written like that :

One two
Three four
Five six
(empty line)

The cout will display two "six" strings. Is it a problem related to the \r\n of Windows or something like that ? I use Microsoft VC++ 2010.

Thanks in advance.

SHR
  • 7,940
  • 9
  • 38
  • 57
Clarens
  • 21
  • 2
  • possible duplicate of [Why is iostream::eof inside a loop condition considered wrong?](http://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered-wrong) – Zac Howland Oct 28 '13 at 13:53
  • 3
    Your entire problem boils down to this: `while (!inFile.eof())` <-- Don't do that! – Zac Howland Oct 28 '13 at 13:54
  • ... while (inFile >> buffer) ... Seems to work fine. As explained in http://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered-wrong, thanks Zac. – Clarens Oct 28 '13 at 14:14

2 Answers2

3

Using stream.eof() for loop control us normally wrong: you always want to check the result after reading:

while (inFile >> buffer) {
    ...
}

The formatted read will start with skipping leading whitespace. After that, the string extractor will read non-whitespace characters. If there is no such character, the extraction fails and the stream converts to false.

Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380
0

Before the read it wasn't EOF yet. But last read action has failed due to EOF reach.

You can use fail to check if your last read failed:

int main () {
    ifstream inFile("test.txt");
    string buffer;
    while (!inFile.eof()) {
        inFile >> buffer;
       /**EDIT**/
       if(!inFile.fail()){
            cout << buffer << endl;
        }else{
            cout << endl;
        }
    }
    return 0;
}
SHR
  • 7,940
  • 9
  • 38
  • 57
  • When I try your code the inFile.gcount() always returns 0. I guess that the operator<< doesn't increment the gcount. – Clarens Oct 28 '13 at 14:10
  • You do not want to do this kind of operation using `while (!istream::eof())`. It will always make your code far more complicated than it would be otherwise. – Zac Howland Oct 28 '13 at 14:19
  • You were right my mistake. I've edited the answer. for this you can use `if(!inFile.fail())` – SHR Oct 28 '13 at 14:39