两次阅读C ++ ifstream吗? [英] reading a C++ ifstream twice?
问题描述
如何使用 std :: ifstream
两次读取文件(例如,像旧的两遍汇编程序一样)?
How to read a file twice (e.g. like an old two-pass assembler do) using 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;
}
并且它不起作用(第二个循环无限循环)。
and it does not work (the second loop is looping indefinitely).
FWIW,在Linux / x86-64 / Debian上使用GCC 4.9.2编译
FWIW, compiling with GCC 4.9.2 on Linux/x86-64/Debian
实际上,我正在尝试解析由 ** somename
等行组成的文件,其后(在下一行中)是JSON对象,后面跟着一些空的换行符(然后再重复一次 ** someothername
后面跟着另一个JSON对象等)。我需要一个两遍算法。第一步是提取所有名称(例如 somename
)并构建一些空命名的事物。第二遍是从命名对象后面的JSON对象填充命名的东西。 JSON解析是使用最新的1.5 jsoncpp
库完成的。
Actually I am trying to parse a file made of lines like ** somename
followed (in the next lines) by a JSON object, followed by some empty newlines (and repeatedly again perhaps a ** someothername
followed by another JSON object etc...). I need a two-pass algorithm. The first pass is extracting all the names (like somename
) and building some "empty" named things. The second pass is filling the named things from the JSON object following them. JSON parsing is done using a recent 1.5 jsoncpp
library.
推荐答案
最后一次调用 std :: getline
到达流结束时失败,设置 故障位
。由于设置了故障位
,因此对 seekg
无效。您需要 清除
调用 seekg
之前的流状态标志( DEMO ):
The last call to std::getline
upon reaching end-of-stream fails, setting failbit
. Since failbit
is set, the call to seekg
has no effect. You need to clear
the stream's status flags before calling seekg
(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);
}
这篇关于两次阅读C ++ ifstream吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!