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

Is it OK to continue reading from stream after failure?

我正在使用以下循环从两个文件中读取数字,直到两个文件都用完为止:

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
}

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

简短回答:是的,您可以根据需要多次尝试从流中输入内容。即使在尝试从该流输入内容失败之后。将发生的只是在尝试输入内容失败后所有尝试输入内容的尝试也将失败。

长答案:operator >> 表现为格式化输入函数 [istream.formatted.arithmetic]. Formatted input functions construct a local sentry object and only perform input if converting that sentry object to bool results in the value true [istream.formatted.reqmts]. By default (if you did not override this behavior by supplying custom character traits to the stream), an object of type std::sentry will be used. An std::sentry that has been constructed for a stream will evaluate to true only if good() was true [istream::sentry]. good() only returns true if neither failbit nor badbit nor eofbit are set [iostate.flags]/7. If operator >>(int&) attempts to input (due to successful construction and check of the sentry) but fails to do so, it will set the failbit [istream.formatted.arithmetic]/3. If the corresponding flag in the exception mask of the stream is set (it is not set by default), setting the failbit will result in an exception being thrown [iostate.flags]/6 [iostate.flags]/5。否则,流将简单地处于失败状态并且哨兵对象的构造将导致下一次 false 直到您调用 clear()

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

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

是的,你可以做到。一旦流处于失败状态 (failbit),进一步的读取也将失败,但这是您希望发生的情况。这些读取将 不会 抛出异常 - 如果通过流的 exceptions() method. According to this source 显式启用,则 failbit 只会生成异常,默认情况下这些异常未启用:

All streams have goodbit by default (they do not throw exceptions due to error state flags being set).