关于ifstream如何读取行和列的C++问题

C++ question regarding how ifstream reads lines and columns

我在阅读我的一些旧代码时发现我并不完全了解 ifstream 是如何工作的。下面的代码应该只读取一个文件,将其内容保存到一个对象中,然后创建另一个具有完全相同数据的文件,写为:

#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;
}

与“data.txt”有:

23.5    10.1    11.6
14.3    8.2     9.3
6.5     6.7     5.3

代码工作得很好,但我不知道 ifstream 如何“知道”在给定时刻它应该在哪一行或哪一列,因为变量 i 不用于控制 myfile。我假设默认情况下 ifstream 有两个内部变量,一个用于行,另一个用于列,每次识别 myfile >> xxx 命令时,列变量都会递增,每次循环重复时,行变量是递增。 是这样的吗?实际上不控制代码在给定时刻的行或列让我很困惑。 比方说,在这个例子中我只想读取第二行和第二列的数据。我可以使用 'myfile[1][1] >> xxx' 等显式表达式直接访问它吗?我想 getline 可以使用,但由于它用于字符串我真的不知道。

read_file()中,读取发生在这个循环中:

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

首先,这假设 data[] 已经分配了足够数量的元素。奇怪了,文件还没有读取,怎么知道要读取多少条记录呢?

那么,这个读取算法假设数据在一个普通的文本文件中,其中数据元素被space分隔:

  • myfile >> data[i].grade1读取新序列的第一级。如果它到达文件末尾,结果将被评估为 false 并且循环将结束。

  • 然后对于每个一年级读取,循环读取记录的下一个年级:myfile >> data[i].grade2 >> data[i].grade3;

这个逻辑实际上是一个接一个地读取数字。唯一的限制是数字之间有一个或几个space。因此,流不关心列:它只是要读取的下一个项目。
以下输入文件同样有效:

23.5    
10.1    
11.6
14.3    8.2
9.3 6.5 6.7 5.3

也就是说,不需要在函数结束时关闭和清除流:当函数 return 时,它的本地对象将被销毁。这包括流对象,销毁确保一切正确结束。

备注:不完整的记录不好处理:如果有第一个等级,但缺少一个剩余等级,流将处于错误状态,grade2grade3元素将保持未初始化状态。