cout repeats last stored line of file

I'm working on a group project wherein we do some beginner-level data mining on an XML file. We are to read the timestamp and voltage data values from each VoltAmpereReactiveTimeSeries element in the file, neither of which are located at the end of the file.
The program I created has a bit of an error: Sometime after successfully retrieving and outputting all the timestamps, the program prints an empty timestamp and the last recorded set of the aforementioned data values.
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

void getDataValues(ifstream &inFile, int dataValues[25])
{
    if (!inFile.eof())
    {
        string dataValueString;
        getline(inFile, dataValueString);
        stringstream datasstream;
        datasstream = stringstream(dataValueString);
        for (int i=0; i < 25; i++) {
            datasstream >> dataValues[i];
        }
    }
}

  int main(int argc, const char * argv[]) {
    ifstream inFile;
    inFile.open("OperationActive.xml");
    if (!inFile.good()) {
        cout << "Could not read data.xml.";
    }
    else
    {
        while (inFile.good()) {
            string timestamp = getTimestamp(inFile);
            cout << "Timestamp: " << timestamp << endl;
            int dataValues[25];
            getDataValues(inFile, dataValues);
            cout << "Data values:";
            for (int i=0; i < 25; i++) {
                cout << " " << dataValues[i];
            }
            cout << endl;
        }
    }
    return 0;
}
Do not loop on !eof(). 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 >> operation as the condition in the while statement.
1
2
3
  while (cin >> var) 
  {  //  Good cin or istream operation
  }


In your case, at line 4 you're testing eof(). eof bit is not set yet. At line 7 you attempt to read a line. This fails because you've hit eof, yet you proceed without checking that getline() succeeded. dataValueString still has the previous record in it.

AbstractionAnon:

Hmm, and I thought I'd "done my due diligence", as it were, by having the check in place in my getDataValues. Thanks
Topic archived. No new replies allowed.