Home > Software engineering >  C question regarding how ifstream reads lines and columns
C question regarding how ifstream reads lines and columns

Time:12-31

I was reading some old codes of mine and I realize that I don`t know exactly how ifstream works. The following code should just read a file, save its contents into an object and create another file with exactly same data, which is written as:

#include <iostream>
#include <fstream>

using namespace std;

class grade {
  public:
    float grade1;
    float grade2;
    float grade3;
};

void read_file(grade data[]){
    ifstream myfile("data.txt");
    int i=0;
    while(myfile >> data[i].grade1){
            myfile >> data[i].grade2 >> data[i].grade3;
            i=i 1; }
    myfile.close();
    myfile.clear();
}

void write_file(grade data[]){
    ofstream myfile("data_out.txt");
    for(int i=0; i<3; i  ){
        myfile << data[i].grade1 << "\t" << data[i].grade2 << "\t" << data[i].grade3 << endl;
    }
    myfile.close();
    myfile.clear();
}


int main()
{
    grade data[3];
    read_file(data);
    write_file(data);

    return 0;
}

With "data.txt" having:

23.5    10.1    11.6
14.3    8.2     9.3
6.5     6.7     5.3

The code works just fine, but I don't get how the ifstream "knows" which line or column it should be at a given moment, since the variable i is not used to control myfile. I am assuming that by default ifstream has two internal variables, one for line and the other for column, that each time a myfile >> xxx command is identified, the column variable is incremented and every time that a loop repeats the line variable is incremented. It is something like that? Not actually controlling what line or column the code is at a given moment is quite confusing to me. Lets say, for instance, that in this example I would like to read only the data on the second line and column. Could I access directly it using some explicit expression like 'myfile[1][1] >> xxx'? I guess that getlinecould be used, but since it is used for strings I really don't know.

CodePudding user response:

In read_file() the reading occurs in this loop:

int i=0;
while(myfile >> data[i].grade1){
        myfile >> data[i].grade2 >> data[i].grade3;
        i=i 1; }

First, this assumes that data[] was already allocated with sufficient number of elements. It's strange since the file was not yet read, so how to know how many records are to be read in advance?

Then, this reading algorithm assumes that the data is in an ordinary text file, in which data elements are space separated:

  • The myfile >> data[i].grade1 reads the first grade of a new sequence. If it reaches the end of file, the result will be evaluated to false and the loop will end.

  • Then for every first grade read, the loops reads the next grades of the record: myfile >> data[i].grade2 >> data[i].grade3;

This logic reads in fact one number after the other. The only constraint is that there are one or several spaces between the numbers. The stream therefore doesn't care about columns: it's just the next item to be read.
The following input file would work equally well:

23.5    
10.1    
11.6
14.3    8.2
9.3 6.5 6.7 5.3

This being said, no need to close and clear the stream at the end of the function: when the function will return, its local objets will be destroyed. This includes the stream object, and the destruction ensures that everything ends right.

Remark: incomplete records are not handled well: if the first grade is present but one of the remaining is missing, the stream will be in an error state, and the grade2 or grade3 elements will be left uninitialized.

  • Related