我想从以下字符串的数组(存储在文件中)中打印控制台中的每个对象:
{ beforechars [{Object1},{Object2},{Object3}] afterchars }
我这样做:
std::ifstream is("content.txt");
std::getline(is, content, '[');
while (std::getline(is,content,'{')) {
std::getline(is,content,'}');
std::cout << content << std::endl;
}
in.close();
但是我得到了这个输出:
Object1
Object2
Object3
] afterchars }
我的理解是,在Object3
次迭代后,ifstream
应该有“}] afterchars} ”并且while的后卫不应该是真的,因为没有任何' {'char ...我是对的?错误在哪里?
答案 0 :(得分:6)
while条件并不像您期望的那样有效:getline()
会成功读取,直到达到&#39; {&#39;或者如果不是文件的末尾。
那么这里会发生什么?
Object3
时,您在流中的排名是在结束'}'
之后。 getline()
条件中的while
会将所有剩余的文件读入content
,因为它遇到没有'{'
。因为它可以成功读取某些内容,所以条件评估为true。 getline()
块中的while
无法读取任何内容,因此content
将保持不变。然后流处于失败状态。在您清除此状态之前,后续操作不会成功。但是现在你的代码中没有任何可见的东西。 简单的解决方法:
一个非常简单的解决方法是在查找'{'
之前保持流中的当前位置,如果找不到,请返回此位置。注意:从性能的角度来看,这种解析文件的方式并不是那么好,但对于小文件来说它是可以的。
std::getline(is, content, '[');
auto pos = is.tellg(); // read current position
while (std::getline(is,content,'{') && !is.eof()) {
std::getline(is,content,'}');
pos = is.tellg(); // update position before iterating again
std::cout << content << std::endl;
}
is.seekg(pos); // and get back to last position
这里的诀窍是,如果找不到'{'
,则getline()
流尚未处于失败状态,但eof()
已经为真。然后我们可以结束循环并返回到最后记录的位置。
<强> Online demo 强>
答案 1 :(得分:1)
std::getline
读取字符,直到分隔符(使用它)或直到流的结尾。只有在没有消耗字符时才会在流上设置failbit(在空/无效流上调用)。
因此,只有当流为空时,你的循环才会终止。
Streams界面只允许查看下一个字符,没有办法扫描输入,如果存在特定字符则执行读取。
如果需要随机访问字符,则需要读取字符串中的输入,然后解析它(使用正则表达式或其他内容。)