1

Assume that we have a file A with the following format:

0 5
1 10
2 10
5 0
10 5

which represents all directed edges of some graph like 0 > 5, and so on. The file is sorted based on the left node. Now assume that we have some machines and each machine is doing some calculations for a set of nodes like:

Machine 1: for {0,1}
Machine 2: for {2,5}
Machine 3: for {10}

As shown above the sets are sorted i.e. machine i will have nodes with smaller indices than machine i+1. The calculations depend on the edges leaving from each node so I am trying to read file A for Machine 1 then for Machine 2 and then Machine 3 line-by-line and for each of them exit a loop when I reach the last edge leaving from the last node the machine is responsible for. The file is read by some Master Machine that is allocating jobs. For the above example:

For Machine 1
Loop through lines 
0 5
1 10
Exit loop

For Machine 2
Loop through lines 
2 10
5 0
Exit loop

For Machine 3
Loop through lines 
10 5
Exit loop

I have the following C++ code:

ifstream graph_file;
graph_file.open("graph.txt");

//...

string line;
unsigned long left_node;
while(1){

    //EOF reached. Break.
    if (graph_file.eof()){
        break;
    }

    getline(graph_file, line);
    left_node = stol(line);

}

Imagine that we are done with Machines 1 and 2 (code not shown but works fine) and the file pointer points to the line of the input file where Machine 3 should start from. So std::getline() reads the last line of the above example and at the next iteration the loop doesn't break since the flag is not EOF so the std::stol() throws std::invalid_argument since it reads nothing.

Why is this behavior?

mgus
  • 768
  • 3
  • 14
  • 31
  • It doesn't set `EOF` until you attempt to read and experience an input failure. If the read succeeds -- no `EOF`, but once you loop again -- on your next attempt -- wham! Then you attempt `stol(line)` after the failed call to `getline`. (*undefined behavior*) – David C. Rankin May 10 '18 at 05:11

1 Answers1

2

Same reason as why eof() in a loop condition does not work. Notice that your code is basically the exact same as while(!graph_file.eof()) since you're checking the condition at the start of the loop, which is exactly what a normal while loop does.

eof() only gets set on the first attempt to read past the end of the file. If there is a newline at the end which stops the input, the flag does not get set.

The fix is in the link at the top of this answer.

BessieTheCookie
  • 4,571
  • 4
  • 13
  • 32