while(file.good()&&!file.eof()) run once more

Hi,

When I run the following code, the while loop will run more once time.

The file contents are:

A_LABEL,A_NAME
B_LABEL,B_NAME
C_LABEL,C_NAME(END OF FILE)

However, when I run the code, and cout to test, the result is something like following:

1.st: label=A_LABEL, name=A_NAME
2.nd: label=B_LABEL, name=B_NAME
3.rd: label=C_LABEL, name=C_NAME
4.th: label='',name=C_NAME

So totally while loop run 4 times. But it should be only three time.

if (file.is_open()){
while (file.good() && !file.eof())
{
getline ( file, label, ',' );//label is a string
getline ( file, name, '\n' );//name is a string

label.erase(std::remove(label.begin(), label.end(), ' '), label.end());

name.erase(std::remove(name.begin(), name.end(), ' '), name.end());

///TODO

}//end while
}//end if

Thank you.
Best
Last edited on
the crude, quick fix

while(..)
{
getline(...
if(!file.eof())
getline(...)
if(!file.eof)

...

You can also re-write the loop to avoid having to do that logic. There are examples in the forums on this, or the web, and I can't type much right now.



It's always wrong to check the stream status in the loop condition. It is possible to work around that wrong piece of code to make it work, but it's best to do it right to start with.

To do it right, realize what you're testing: file.good() and file.eof() and all other stream status tests answer the question: "did the last read complete successfully?". To use that test correctly you need to read, then test. As in jonnin's example above, or, if you don't need to take different branches between eof and errors, just look at the result of the input operation directly:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <fstream>
#include <iostream>
#include <string>
#include <algorithm>
int main()
{
    std::ifstream file("test.txt");
    std::string label, name;
    while (getline(file, label, ',') && getline(file, name))
    {
      label.erase(std::remove(label.begin(), label.end(), ' '), label.end());
      name.erase(std::remove(name.begin(), name.end(), ' '), name.end());
      std::cout << "label = " << label << " name = " << name << '\n';
    }
}

live demo http://coliru.stacked-crooked.com/a/81b33515d5c38de1

Last edited on
Wow, amazing, thank you Cubbi and jonnin!
I am also curious why this '' happens in the 4.th loop
As cubbi explained, you read 3 records. No problem. The file is conceptually at eof, but the eof condition has not been set yet. The eof flag will only be set when you attempt a read and there is no record to be read.

At the top of the loop for the 4th iteration, eof is still false. You proceed to attempt two getline operations. Neither one succeeds because the eof flag has now been set. You then proceed with a couple of erases as if the getlines had succeeded.
Topic archived. No new replies allowed.