reading garbage after eof

I am reading values from file filling up a std::vector. Everything works fine but it happens I read in some extra garbage and push it in my vector. More precisely

some types I need

1
2
3
4
5
6
typedef std::complex<double> dcomp;
//typedef dcomp impT[2][2];
typedef std::array<std::array<std::complex<double>, 2>, 2> impT;
enum{X,Y,Z};
const dcomp ic(0.,1.);


reading section
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

    
    std::ifstream dFile(dataFile);
    if (dFile.is_open()) {
        
        double T_l;
        double re[2][2];
        double im[2][2];
        impT d_l;
        
            do{ // RISK, if file is corrupted I can read in garbage.
            dFile >> T_l >> re[X][X] >> re[X][Y] >> re[Y][X] >> re[Y][Y]
            >> im[X][X] >> im[X][Y] >> im[Y][X] >> im[Y][Y];
            for (int i = 0; i<2; i++) {
                for (int j=0; j<2; j++) {
                    d_l[i][j] = re[i][j] + ic*im[i][j];
                }
            }
            data.push_back(d_l);
            period.push_back(T_l);
        
        }while(!dFile.eof());
    } else {
        std::cout << "could not open file " << dataFile << "\n";
    }


my input file has 41 lines of nine entries each.
If I check the vector size in the debugger is 42, being the last element garbage.

I know the trivial solution will be to get rid of the last element, but I rather prefer to understand what am I doing wrong.
Last edited on
I know the trivial solution will be to get rid of the last element, but I rather prefer to understand what am I doing wrong.

Actually the real trivial solution would be not to try to read past the end of file. If you used a while loop with the actual read operation as the condition you wouldn't be having the problem.

1
2
3
4
5
6
7
8
9
10
11
            while(dFile >> T_l >> re[X][X] >> re[X][Y] >> re[Y][X] >> re[Y][Y]
            >> im[X][X] >> im[X][Y] >> im[Y][X] >> im[Y][Y]){ // NO RISK, if file is corrupted the read stops, bad read will not be added to the vectors.
            for (int i = 0; i<2; i++) {
                for (int j=0; j<2; j++) {
                    d_l[i][j] = re[i][j] + ic*im[i][j];
                }
            }
            data.push_back(d_l);
            period.push_back(T_l);
        
        }
To expand on what jlb posted:

Do not loop on (! stream.eof()) or (stream.good()). This does not work the way you expect. The eof bit is set true only after you make a read attempt on the file. This means after you read the last record of the file, eof is still false. Your attempt to read past the last record sets eof, but you're not checking it there. You proceed as if you had read a good record. This will result in reading an extra (bad) record. The correct way to deal with this is to put the >> (or getline) operation as the condition in the while statement.
1
2
3
  while (stream >> var) // or while (getline(stream,var))
  {  //  Good operation
  }
Last edited on
cool, I was aware how to do this by reading a single value, I didn't know it was possible to concatenate a set of reads under while condition.

Thanks a million
Topic archived. No new replies allowed.