Extra output while reading file

I wrote a program to read real numbers from a file,
program is supposed to give 5 output ,as there are 5 list of numbers but I'm getting last numbers list repeated.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include<iostream>
#include<fstream>
#include<string>
using namespace std;
int main(){
  //  std::ios::sync_with_stdio(false); // to speed up reading
    ifstream testfile;
    string line;
    uint_fast16_t n,i=0;
    float lat1,lat2,lng1,lng2;
    testfile.open("testfile.txt");
    if (!testfile) {
        cout << "Unable to open file";
        exit(1); // terminate with error
    }
    testfile.seekg(19,ios::beg);//skip to last of first line
    testfile>>n;
    testfile.seekg(21,ios::beg);
    getline(testfile,line);//read next line;
    
 while (!testfile.eof())
        {getline(testfile,line,' ');
testfile>>lat1;testfile>>lng1;testfile>>lat2;testfile>>lng2;

cout<<" "<<lat1<<" "<<lng1<<" "<<lat2<<" "<<lng2<<endl;
        }
        testfile.close(); // Step 5: Closing file


return 0;
}


file contents;

1
2
3
4
5
6
7
Number_Of_Location=5
Location'Number' Northwest_Latitude NorthEast_Longitude SouthEast_Latitude SouthEast_longitude
Location1 20.2783121 85.7684699 20.2722087 85.7817819
Location2 28.9763977 77.636981 28.973047 77.6388145
Location3 28.9756777 77.638032 28.9736137 77.642148
Location4 29.9827777 78.1222222 29.9755555 78.1325000
Location5 29.9788888 78.0630555 29.9608333 78.0841666


output:
20.2783 85.7685 20.2722 85.7818
28.9764 77.637 28.973 77.6388
28.9757 77.638 28.9736 77.6422
29.9828 78.1222 29.9756 78.1325
29.9789 78.0631 29.9608 78.0842
29.9789 78.0631 29.9608 78.0842 - repeated output, why is this happening?
@Sholi, I think you have made this exercise spectacularly difficult for yourself.

Your use of seekg for positioning completely crippled my system.

Your use of .eof as a test doesn't work because you don't actually reach the end of file until you try (and fail) to read another item. When the test fails at this point you have already entered the while loop, so failure to read new values leaves you with the previously read ones.

Try this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main()
{
    ifstream testfile( "testfile.txt" );
    string line, name;
    double lat1, lat2, lng1, lng2;

    for ( int header = 1; header <= 2; header++ ) getline( testfile, line);     // ignore header lines
    
    while ( testfile >> name >> lat1 >> lng1 >> lat2 >> lng2 )
    {
       cout << lat1 << " " << lng1 << " " << lat2 << " " << lng2 << '\n';
    }

    testfile.close();
}

20.2783 85.7685 20.2722 85.7818
28.9764 77.637 28.973 77.6388
28.9757 77.638 28.9736 77.6421
29.9828 78.1222 29.9756 78.1325
29.9789 78.0631 29.9608 78.0842
Last edited on
The main problem is your indentation is deceptive, but the issue you complain about is probably caused by this line:
while (!testfile.eof())

The stream will enter in the EOF condition after having read the last line, therefore your loop will execute one more time. The most common solution is to check the stream status directly.

Just to compare:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <fstream>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>


int main()
{
    std::ifstream testfile("testfile.txt");

    if (!testfile) {
        std::cout << "Unable to open file.\n";
        std::exit(1); // terminate with error
    }

    std::string line;
    std::getline(testfile, line);

    // Get the number of the end of first line:
    line = line.substr(line.find_last_of('=') + 1);
    std::istringstream iss { line };
    uint_fast16_t loc_num;
    iss >> loc_num;
    std::cout << "There are " << loc_num << " coordinates in the file:\n";

    // Get ditch of the heading line:
    std::getline(testfile, line);

    // Read the coordinates:
    while(std::getline(testfile, line)) {
        iss.clear();
        iss.str(line);
        double lat1, lat2, lng1, lng2;
        iss >> line >> lat1 >> lat2 >> lng1 >> lng2;
        std::cout << line << ':' << std::fixed << std::setprecision(7)
                  << std::setw(11) << lat1
                  << std::setw(11) << lng1
                  << std::setw(11) << lat2
                  << std::setw(11) << lng2
                  << '\n';
    }

    // Redundant so far: the file stream will be automatically closed at the
    // end of the function:
    // testfile.close();
    return 0;
}

@Enoizat I'm not getting why loop will run again,
when reading last line , last line gets printed,
EOF is true : so while should stop,
& even if while doesn't stops,(as u say) how are the values lat1,lat2,lng1,lng2 are getting updated with same values as their previous one?
@lastchance ,thanks for providing me a better solution, but I still dont understand that

while loop will execute (!testfile.eof()) & then proceed statements , if (!testfile.eof()) is true which isn't in this case
Sholi wrote:
EOF is true : so while should stop,
& even if while doesn't stops,(as u say) how are the values lat1,lat2,lng1,lng2 are getting updated with same values as their previous one?


No, EOF is NOT true at this point ... nor are lat1, lat2, lng1, lng2 getting updated. (They are simply stuck with their previous values.)

When it has read the last line of data ... it is at the end of that line of data. It does not know about EOF UNTIL IT TRIES TO READ THE NEXT PIECE OF DATA. At that point, because the while() condition is true it has to complete the loop. It fails to read any new data into the variables ... which just retain their values from the previous read, so that is what is printed out. One way to confirm that would simply be to set them to some recognisable sentinel value immediately after you cout them.


As a general principle, DON'T TEST FOR EOF ... test for the condition of the stream. As in both mine and @Enoizat's examples you can conveniently do that within the while() test. Neither of us use EOF.

It happens wearyingly often:
https://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-i-e-while-stream-eof-cons
Last edited on
Topic archived. No new replies allowed.