底线顶部: 在正确处理空白的情况下,eof
可以使用以下方法(甚至比fail()
错误检查更可靠):
while( !(in>>std::ws).eof() ) {
int data;
in >> data;
if ( in.fail() ) /* handle with break or throw */;
// now use data
}
(感谢Tony D提出的突出显示答案的建议。请参见下面的评论,以获取一个示例,说明为什么此方法更可靠。)
反对使用的主要论点eof()
似乎缺少关于空白的重要意义。我的主张是,eof()
明确地检查不仅不仅“ 永远是错误的 ”(在该线程和类似的SO线程中似乎是压倒一切的观点),而且通过正确处理空白,它还提供了一种更清洁,更可靠的方法错误处理,并且始终是正确的解决方案(尽管不一定是最糟糕的解决方案)。
总结一下建议的“正确”终止和读取顺序如下:
int data;
while(in >> data) { /* ... */ }
// which is equivalent to
while( !(in >> data).fail() ) { /* ... */ }
由于超出eof的读取尝试而导致的失败被视为终止条件。这意味着,除了eof之外,没有简单的方法来区分成功的流和确实失败的流。采取以下流:
1 2 3 4 5<eof>
1 2 a 3 4 5<eof>
a<eof>
while(in>>data)
结束了一组failbit
用于所有三个输入。在第一和第三,eofbit
也设置。因此,经过循环之后,需要非常难看的额外逻辑来区分正确的输入(第一)和不正确的输入(第二和第三)。
而采取以下措施:
while( !in.eof() )
{
int data;
in >> data;
if ( in.fail() ) /* handle with break or throw */;
// now use data
}
在这里,in.fail()
验证只要有什么要阅读的东西,它就是正确的东西。它的目的不仅仅是一个while循环终止符。
到目前为止,一切都很好,但是如果流中存在尾随空间,会发生什么?听起来像是对eof()
终结者的主要关注?
我们不需要放弃错误处理。只是吃掉空白:
while( !in.eof() )
{
int data;
in >> data >> ws; // eat whitespace with std::ws
if ( in.fail() ) /* handle with break or throw */;
// now use data
}
std::ws
在设置eofbit
而不是时failbit
跳过流中任何可能的(零个或多个)尾随空间。因此,in.fail()
只要至少要读取一个数据,它就会按预期工作。如果全空白流也可接受,则正确的格式为:
while( !(in>>ws).eof() )
{
int data;
in >> data;
if ( in.fail() ) /* handle with break or throw */;
/* this will never fire if the eof is reached cleanly */
// now use data
}
简介:正确构造while(!eof)
不仅是可能的,而且不是错误的,但允许在范围内对数据进行本地化,并且将错误检查与通常的业务进行了更清晰的分离。话虽如此,这while(!fail)
无疑是一个更常见,更简洁的习惯用法,并且在简单(每种读取类型的单个数据)场景中可能是首选。
scanf(...) != EOF
在C中也不起作用,因为scanf
返回成功解析和分配的字段数。正确的条件是格式字符串中的字段数scanf(...) < n
在哪里n
。