我正在尝试从C++中的文本文件中输入数据。文本文件的格式为:
4 15
3 516
25 52 etc.
每行包含两个整数。我不知道文件中的行数,所以我可以绑定足够的内存,这就是我解决这个问题的方法:
ifstream filein;
filein.open("text.txt",ios::in);
int count=0;
while (!filein.eof())
{
count++;
filein>>temporary;
}
count=count/2; // This is the number of lines in the text file.
我的问题是我想不出重置的方法
中的文件
进入初始状态(直到文件开始,这样我就可以实际输入数据),而不是关闭输入流并再次打开它。还有别的办法吗?
我不回答你问的问题,而是回答你没有问的问题:
Q: 如果我不知道文件中有多少行,我如何读取文件的所有行?
A: 使用std::vector<>
。
如果你想读取所有的数字,无论配对:
// all code fragments untested. typos are possible
int i;
std::vector<int> all_of_the_values;
while(filein >> i)
all_of_the_values.push_back(i);
如果你想读入所有的数字,将交替的数字放入不同的数据结构中:
int i, j;
std::vector<int> first_values;
std::vector<int> second_values;
while(filein >> i >> j) {
first_values.push_back(i);
second_values.push_back(j);
如果你想读入所有的数字,可以将它们存储在某种数据结构中:
int i, j;
struct S {int i; int j;};
std::vector<S> values;
while(filein >> i >> j) {
S s = {i, j};
values.push_back(s);
}
最后,如果您想一次读取一行文件,请保留每行的前两个数字,丢弃每行的剩余部分,并将其存储为用户定义的数据结构:
std::vector<MyClass> v;
std::string sline;
while(std::getline(filein, sline)) {
std::istringstream isline(sline);
int i, j;
if(isline >> i >> j) {
values.push_back(MyClass(i, j));
}
}
旁白:永远不要在循环条件中使用
eof()
或good()
。这样做几乎总是会产生错误代码,就像在您的情况下一样。相反,我更喜欢在条件中调用输入函数,就像我上面所做的那样。我认为@Robᵩ有一个非常正确的想法——而不是读取所有数据来计算行数,然后再次读取整个文件来实际读取数据,使用类似std::vector
(或std::deque
)的东西,在读取数据时会根据需要进行扩展。
然而,在典型的情况下,一行上的两个数字将相互关联,您通常希望以直接显示关联的方式存储它们。例如,它们可能是点的X和Y坐标,在这种情况下,您需要读取点:
class point {
int x, y;
};
std::istream &operator>>(std::istream &is, point &p) {
return is >> p.x >> p.y;
}
std::ifstream in("myfile.txt");
// create the vector from the data in the file:
std::vector<point> points((std::istream_iterator<point>(in)),
std::istream_iterator<point>());
稍有不同的是:即使您决定使用显式循环,也请不要使用while (!whatever.eof())
来执行——这几乎肯定会失败。您想要检查读取数据是否成功,所以(例如)使用上面的point
类,您可以使用类似于的东西
point p;
while (infile >> p)
points.push_back(p);
函数为:filein.seekg (0, ios::beg);
这是一个参考
如果您这样做的话,还应该使用filein.clear()
来重置文件中的eof
位。
当然,如果你想要最好的方法来完成你最终要做的事情,Robᵩ'她的答案要好得多,尽管涉及面更广。