关于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 时,它的本地对象将被销毁。这包括流对象,销毁确保一切正确结束。
备注:不完整的记录不好处理:如果有第一个等级,但缺少一个剩余等级,流将处于错误状态,grade2
或grade3
元素将保持未初始化状态。
我在阅读我的一些旧代码时发现我并不完全了解 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 时,它的本地对象将被销毁。这包括流对象,销毁确保一切正确结束。
备注:不完整的记录不好处理:如果有第一个等级,但缺少一个剩余等级,流将处于错误状态,grade2
或grade3
元素将保持未初始化状态。