为什么 in.good() 与 !in.fail() 不同?

Why isn't in.good() the same as !in.fail()?

本文关键字:in 不同 fail 为什么 good      更新时间:2023-10-16

我读到以下内容是一种反模式:

while(in.good()) {
    // ...
}

但这是首选:

while(operation) {
}

但是,流有一个返回 !fail() 的 bool 转换运算符。!fail()不是和good()一样吗?如果不是,为什么这两个函数不对称?我希望它类似于true == !false.

http://en.cppreference.com/w/cpp/io/basic_ios/good 有一个很好的表格,解释了std::istream的状态以及各种函数返回的值。

while ( stream.good() )while(stream)的唯一不同时间是成功读取流的内容并达到EOF时。那时,stream.good()返回true,而(bool)stream的计算结果为false.

如果上一个读取操作成功而没有遇到EOF,则in.good()为真。(即使读取操作成功,也可能遇到 EOF。因此,如果in.good()为 false,则上一个读取操作失败(在这种情况下,下一个读取操作也将失败(或遇到 EOF(在这种情况下,下一个读取操作也将失败(。因此,如果in.good()为 false,则下一次读取操作肯定会失败。如果我们想知道是否值得尝试执行读取操作,我们应该测试 in.good() .

in.good()是真的这一事实并不能保证任何事情。假设in以空格结尾,这通常是这种情况,因为文本文件需要以换行符结尾。格式化读取操作在第一个空格字符处停止,并将其unget回输入流中,因此,如果上一个读取操作读取最后一个数据项,它仍然不会在 EOF 处离开流,并且in仍将good。[见注1]。因此,如果您的循环如下所示:

while (in.good()) {
  in >> x;
  /* Do something with x assuming that it is valid */
}

然后,您不会注意到最后一个in >> x何时失败,并且最终将在最后一个循环中使用未定义的值 x。(可能最后一个值将被处理两次。

如果您的循环while (!in.bad())while (!in.eof()),也会发生同样的事情。

你真正想要的是检查in >> x是否成功。没有别的。而经典的方法是:

while (in >> x) {
  /* If we get here, x has a legitimate value */
  ...
}

in >> x只返回in,所以这完全等同于

while (in >> x, in) {
  /* ... */
}

换句话说,bool(in) false上一个操作失败的时间,true成功时精确。这与in.good()不同,因为我们(还(不想测试是否遇到了EOF。

笔记:

  1. 如第一段所述,读取可以成功并设置 EOF。可能发生的一种方式是文件不以换行符结尾。这种情况非常罕见,但你不应该排除它。事实上,它可能会发生,这正是in.bad()不检查 eof 标志的原因:in.bad() false 肯定意味着之前的读取操作失败。

in.good(( 等于: [iOS 文档]

! ( in.eof() || in.fail() || in.bad() )