两次读取C++ ifstream?

7
如何使用std :: ifstream读取文件两次(例如旧的两遍汇编器)?
我尝试了显而易见的方法。
#include <fstream>
#include <iostream>
#include <string>

int main(int argc, char**argv)
{
  std::string path = argc>1?std::string{argv[1]}:std::string(__FILE__);
  std::ifstream inp{path};
  int num=0;
  std::cout << "first pass" << std::endl;
  do {
    std::string lin;
    std::getline(inp,lin);
    if (inp.eof())
      break;
    num++;
    std::cout << "#" << num << ":" << lin << std::endl;
  } while (!inp.eof());
  inp.seekg(0, inp.beg);
  inp.sync();
  std::cout << "second pass" << std::endl;
  num=0;
  do {
    std::string lin;
    std::getline(inp,lin);
    if (inp.eof())
      break;
    num++;
    std::cout << "##" << num << ":" << lin << std::endl;
  } while (!inp.eof());
  inp.close();
  return 0;
}  

而且它不起作用(第二个循环在无限循环)。

顺便说一下,在Linux/x86-64/Debian上使用GCC 4.9.2编译

细节说明

实际上,我正在尝试解析一个由类似** somename的行组成的文件,后面是一个JSON对象,后面是一些空的新行(也许还会重复出现** someothername,然后是另一个JSON对象等等)。我需要一个两遍算法。第一次遍历提取所有名称(如somename),并构建一些“空”的命名事物。第二遍遍历从跟随它们的JSON对象中填充已命名的事物。使用最近的1.5 jsoncpp库进行JSON解析。


5
清除错误标志可能是这样的:inp.clear(); - P0W
第二个循环正在无限循环,并打印什么? - Sergey Kalinichenko
2
我在数月前遇到了这个问题,请查看我的问题回答:https://dev59.com/bl4c5IYBdhLWcg3wFm44 - Raydel Miranda
2
你不应该使用 ifstream::eof() 来控制读取循环,而应该使用文件读取操作来控制循环。这样一旦读取失败,循环就会停止。 - NathanOliver
1
请参阅:https://dev59.com/NW035IYBdhLWcg3wJcYv - sbabbi
显示剩余2条评论
1个回答

6

当到达流的末尾时,std::getline 的最后一次调用失败,设置了 failbit。由于 failbit 被设置,对 seekg 的调用没有效果。在调用 seekg 之前,您需要clear 流的状态标志(DEMO):

namespace {
void one_pass(std::istream& is) {
  std::string lin;
  for (int num = 0; std::getline(is, lin); ++num) {
    std::cout << '#' << num << ':' << lin << '\n';
  }
}
} // unnamed namespace

int main(int argc, char**argv)
{
  std::ifstream inp{argc > 1 ? argv[1] : __FILE__};

  std::cout << "first pass\n";
  one_pass(inp);

  inp.clear();
  inp.seekg(0);

  std::cout << "\nsecond pass\n";
  one_pass(inp);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接