【发布时间】:2011-11-11 22:35:13
【问题描述】:
从 istream 中读取的惯用循环是
while (thestream >> value)
{
// do something with value
}
现在这个循环有一个问题:它无法区分循环是由于文件结尾还是由于错误而终止。比如下面的测试程序:
#include <iostream>
#include <sstream>
void readbools(std::istream& is)
{
bool b;
while (is >> b)
{
std::cout << (b ? "T" : "F");
}
std::cout << " - " << is.good() << is.eof() << is.fail() << is.bad() << "\n";
}
void testread(std::string s)
{
std::istringstream is(s);
is >> std::boolalpha;
readbools(is);
}
int main()
{
testread("true false");
testread("true false tr");
}
对testread 的第一次调用包含两个有效的布尔值,因此不是错误。第二次调用以第三个不完整的布尔值结束,因此是一个错误。然而,两者的行为是相同的。在第一种情况下,读取布尔值失败是因为没有,而在第二种情况下它失败是因为它不完整,并且在两种情况下都命中了 EOF。确实,上面的程序输出了两次相同的行:
TF - 0110
TF - 0110
为了解决这个问题,我想到了以下解决方案:
while (thestream >> std::ws && !thestream.eof() && thestream >> value)
{
// do something with value
}
这个想法是在实际尝试提取值之前检测常规 EOF。因为文件末尾可能有空格(这不会是错误,但会导致读取最后一项没有命中 EOF),我首先丢弃所有空格(不会失败),然后测试 EOF。只有当我不在文件末尾时,我才会尝试读取该值。
对于我的示例程序,它似乎确实有效,我得到了
TF - 0100
TF - 0110
所以在第一种情况下(正确输入),fail() 返回 false。
现在我的问题是:这个解决方案是否保证有效,或者我只是(不)幸运地碰巧给出了预期的结果?另外:是否有更简单的(或者,如果我的解决方案是错误的,是正确的)方法来获得所需的结果?
【问题讨论】:
-
想要的结果是什么?还要检查文件是否有效?你在这两种情况下都有相同的结果......
-
@neagoegab:期望的结果是检测循环是否由于到达文件末尾或由于输入错误而终止。至少在我的实验中,结果不相同,请参见四位数块的第三位:对于非错误情况,它读取 0100,对于错误情况,它读取 0110。因为第三位是
fail()的值,表示至少对于本次测试,fail()可以区分这两种情况。 -
那你的答案是正确的。另请注意,您正在同时验证和处理流。如果这对您来说不是问题,那很好......
-
@neagoegab:惯用循环还同时验证和处理流。
-
我认为惯用循环假设流中的数据是“有效的”......对于示例应用程序来说,无论是什么有效手段。您的第二个字符串不是有效的输入。
标签: c++ error-handling istream