rishabh
rishabh

Reputation: 71

Tellg returning unexpected value

I have a function which reads lines from a file. But before reading it returns the address from where its going to read the next line.

my function is:

void print()
    {
        int j=0;
        string a,b,c,d,e;
        ifstream i("data.txt");
        cout<<setw(15)<<left<<"Hash Value"<<setw(15)<<left<<"Employee Name"<<setw(15)<<left<<"Employee ID"<<setw(15)<<left<<"Salary"<<setw(15)<<left<<"Link"<<endl;
        while(j<10)
        {
            j++;
            cout<<i.tellg()<<endl;
            i>>a>>b>>c>>d>>e;
            cout<<setw(15)<<left<<a<<setw(15)<<left<<b<<setw(15)<<left<<c<<setw(15)<<left<<d<<setw(15)<<left<<e<<endl;
        }
        i.close();
    }

The file it is reading from is data.txt:

      0            ---              0              0             -1
      1            ---              0              0             -1
      2            ---              0              0             -1
      3            ---              0              0             -1
      4            ---              0              0             -1
      5            ---              0              0             -1
      6            ---              0              0             -1
      7            ---              0              0             -1
      8            ---              0              0             -1
      9            ---              0              0             -1

And the output I am getting is:

Hash Value     Employee Name  Employee ID    Salary         Link           
0
0              ---            0              0              -1             
81
1              ---            0              0              -1             
157
2              ---            0              0              -1             
233
3              ---            0              0              -1             
309
4              ---            0              0              -1             
385
5              ---            0              0              -1             
461
6              ---            0              0              -1             
541
7              ---            0              0              -1             
617
8              ---            0              0              -1             
693
9              ---            0              0              -1             

Every line is of length 76 characters. So everytime the address printed should increase by 76. But i dont understand whats going on when the 2nd line is printed[hash value 1], and the 7th line is printed [hash value 6].

Can someone please help me with this?

Upvotes: 0

Views: 225

Answers (1)

James Kanze
James Kanze

Reputation: 153919

A couple of things:

  • First and foremost, you're not reading line by line, so there is no reason to assume that you advance the number of characters in a line each time through the loop. If you want to read line by line, use std::getline, and then extract the fields from the line, either using std::istringstream or some other method.

  • The result of tellg is not an integer, and when converted to an integral type (not necessarily possible), there is no guaranteed relationship with the number of bytes you have extracted. On Unix machines, the results will correspond, and under Windows if (and only if) the file has been opened in binary mode. On other systems, there may be no visible relationship what so ever. The only valid portable use of the results of tellg is to pass it to a seekg later; anything else depends on the implementation.

  • How do you know that each line contains exactly 76 characters? Depending on how the file was produced, there might be a BOM at the start (which would count as three characters if the file in encoded in UTF8 and you are in "C" locale). And what about trailing whitespace. Again, if your input is line oriented, you should be reading lines, and then parsing them.

  • Finally, but perhaps the most important: you're using the results of >> without verifying that the operator worked. In your case, the output suggests that it did, but you can never be sure without verifying.

Globally, your loop should look like:

std::string line;
while ( std::getline( i, line ) ) {
    std::istringstream l( line );
    std::string a;
    std::string b;
    std::string c;
    std::string d;
    std::string e;
    l >> a >> b >> c >> d >> e >> std::ws;
    if ( !l || l.get() != EOF ) {
        //  Format error in line...
    } else {
        //  ...
    }
}

Outputting tellg still won't tell you anything, but at least you'll read the input correctly. (Outputting the length of line might be useful in some cases.)

Upvotes: 3

Related Questions