在失败后继续从流中读取是否可行?

3
我正在使用以下循环从两个文件中读取数字,直到两个文件都读完:
int a, b;
while (file1 >> a, file2 >> b, file1 || file2) {
    if (file1 && file2) ... // use of both a and b
    if (file1) ... // use of a
    if (file2) ... // use of b
}

我的程序可以工作。但是它是否按照标准保证运行?也就是说,我是否被允许从失败的流中继续读取,或者实现可以选择抛出异常?

首先,您必须清除流错误标志。 - Marek R
1
如果你想知道一旦流的失败状态被设置后,是否可以可靠地连续执行失败的读取操作而不会产生任何影响(除了显而易见的:在初始失败后永久性地失败读取),那么是的,你可以。顺便说一句,如果你打算让它变得神秘,恭喜你,你找到了它。 - WhozCraig
@MarekR,它并没有说如果我不清除错误标志,我可能会在我的示例中遇到麻烦。最好提供一个来源(最好是标准的引用)。 - AlwaysLearning
@WhozCraig 是的,不会抛出异常。我来这里是因为我在像cppreference.com这样的地方查找,但没有明确说明(或者对我来说不够明确)。标准对我来说还太晦涩了。 - AlwaysLearning
啊。好吧,只有在你的源代码启用了流异常时才会抛出异常,但是我现在明白了。 - WhozCraig
显示剩余6条评论
2个回答

4

简短回答:是的,您可以尝试从流中输入任意次数的内容,即使之前尝试输入失败了。所有在失败尝试后的输入尝试都将失败。

长答案: operator >> 表现为一个格式化输入函数 [istream.formatted.arithmetic]。 格式化输入函数构造一个本地的sentry对象,只有在将该sentry对象转换为bool时结果为true[istream.formatted.reqmts]时才执行输入操作。 默认情况下(如果您没有通过向流提供自定义字符特征来覆盖此行为),将使用std::sentry类型的对象。已为流构造的std::sentry仅在good()true[istream::sentry]时才会评估为true。只有当failbit、badbit和eofbit都未设置时,good()才会返回true[iostate.flags]/7。 如果operator >>(int&)由于成功构造并检查了sentry而尝试输入但未能输入,则会设置failbit[istream.formatted.arithmetic]/3。 如果流的异常掩码中对应的标志被设置(默认情况下未设置),则设置failbit将导致抛出异常[iostate.flags]/6[iostate.flags]/5。否则,流将处于失败状态,并且下一次构造sentry对象将导致结果为false,直到您调用clear()

我会考虑重写这段代码,例如

do
{
    if (int a; file1 >> a)
        ; // use a
    if (int b; file2 >> b)
        ; // use b
} while (file1 || file2);

我不知道你可以在if的条件语句中声明一个变量,谢谢!但是对于我的第一个if,我想同时使用ab,你有什么建议吗? - AlwaysLearning

0

是的,你可以这样做。一旦流进入失败状态(failbit),进一步的读取也将失败,但这正是你想要发生的。这些读取将不会抛出异常 - 只有在通过流的exceptions()方法明确启用时,failbit才会生成异常。根据this source,默认情况下这些异常未被启用:

所有流默认都具有goodbit(它们不会因设置错误状态标志而引发异常)。


Section/paragraph number? - AlwaysLearning
我指向的来源是一个网站,它没有章节或段落编号。我自己没有阅读过标准文本,我假设我所指向的二手来源的作者读过。 - Nadav Har'El

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