【问题标题】:Is there anyway to reset the filein to the initial state?无论如何将文件重置为初始状态?
【发布时间】:2023-03-17 04:35:01
【问题描述】:

我正在尝试从 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.

我的问题是我找不到重置的方法

文件

进入初始状态(到文件的开头,以便我可以实际输入数据),而不是关闭输入流并再次打开它。有没有其他方法可以做到这一点?

【问题讨论】:

  • 你应该可以使用 seekg (如果我没记错的话)。您是否考虑过只使用矢量?
  • 如果“输入数据”是指将值写回该文件,那么无论如何您都需要以适当的权限打开输出流。
  • @Corbin - seekg 不会清除 eofbit

标签: c++ stream fileinputstream file-io


【解决方案1】:

我不会回答你问的问题,而是回答你没有问的问题,即:

问:如果我不知道文件有多少行,如何读取文件的所有行?

答:使用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()。这样做几乎总是会产生错误的代码,就像您的情况一样。相反,我更喜欢在条件中调用输入函数,就像我在上面所做的那样。

【讨论】:

  • 由于我在使用向量方面经验不足,如何在不知道这些数组大小的情况下将读取的值传递到数组中?我不应该先为这些数组绑定内存吗?
  • 您不能在知道数组大小的情况下将值传递到数组中。如果您是新的 C++ 程序员,不要使用数组。仅应考虑将数组用于高级用途。从更安全、更易于使用的std::vector开始。
  • 非常感谢您的提示和帮助。我将立即研究向量。
【解决方案2】:

我认为@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);

【讨论】:

  • +1 用于显示读取数据的正确习语 -- std::istream_iterator&lt;&gt; 和自定义 operator&gt;&gt;
【解决方案3】:

函数为:filein.seekg (0, ios::beg);

这是Reference

如果您这样做,您还应该使用filein.clear() 重置文件中的eof 位。

当然,如果你想要最好的方法来完成你最终想要做的事情,Robᵩ 的答案要好得多,尽管涉及更多。

【讨论】:

  • 但这留下了eofbit 集。如果他使用seekg,他可能应该先调用ios::clear()。此外,如果文件以空格结尾,您的代码(和他的代码)将增加 count 一倍。
  • @Robᵩ 刚刚注意到如果你调用 filein>>temporary>>wc;那么读取文件就没有问题了,就读取额外的白线而言。
猜你喜欢
  • 1970-01-01
  • 2015-02-21
  • 1970-01-01
  • 2021-01-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-12
  • 2021-09-05
相关资源
最近更新 更多