当初学者开始阅读ifstreams时,他/她的本能是使用通常如下所示的循环来读取文件:
while (!ifstream.eof()
{
...
}
但是,当我使用此代码时,我注意到它直到读取了文件的最后一行两次才停止。C ++程序员注意到,这实际上并不是读取文件的方式。相反,他们通常建议需要读取文件的人使用这样的循环:
while (ifstream >> someVar)
{
...
}
为什么第一段代码总是无法正常工作?
当初学者开始阅读ifstreams时,他/她的本能是使用通常如下所示的循环来读取文件:
while (!ifstream.eof()
{
...
}
但是,当我使用此代码时,我注意到它直到读取了文件的最后一行两次才停止。C ++程序员注意到,这实际上并不是读取文件的方式。相反,他们通常建议需要读取文件的人使用这样的循环:
while (ifstream >> someVar)
{
...
}
为什么第一段代码总是无法正常工作?
Answers:
该while (!ifstream.eof())
循环不工作,因为在C和C ++流/文件时,你已经达到了文件的末尾,但宁可表明,如果你已经尝试阅读不预测过去的文件的末尾。
如果文件的最后一行以换行符(\n
)结束,则大多数读取操作将在遇到该字符时停止读取,并且他们不会检测到该碰巧是文件中的最后一个字符。在下一个读取动作中,甚至可能附加了更多字符,并且读取将成功提取它们。
使用流提取运算符(while (ifstream >> someVar)
)的循环之所以起作用,是因为如果无法提取正确类型的项,则流提取运算符的结果评估为false。如果没有字符可读取,也会发生这种情况。
但是,C ++程序员注意到,总是发生的情况是cin.eof()在读取了最后一行两次之后才返回“ true”。
那不是正在发生的事情。的eofbit
播放没有在转换作用到布尔(stream::operator bool
(或operator void*
在旧的C ++))。仅涉及badbit
和failbit
。
假设您正在读取一个文件,其中包含用空格分隔的数字。基于环的循环cin.eof()
将不可避免地是错误的或充满了if
测试。您要等到EOF才能阅读。您正在阅读数字。因此,使您的代码表达这种逻辑:
while (stream >> some_var) {
process_value(some_var);
}
无论文件的最后一行以结尾0 42\n
还是结尾0 42
(文件最后一行的末尾没有新行),这都将起作用。如果文件以结尾0 42\n
,则最后一次读取将检索值42,并读取行尾的最后一个标记。请注意,尚未读取EOF标记。该函数用process_value
调用42
。流中提取运算符>>下一次调用读取EOF,并且因为没有被提取,无论是eofbit
和failbit
将被设置。
另一方面,假设文件以0 42
(结尾处没有换行符)结尾。最后一次良好读取将检索终止于EOF标记的值42。大概您要处理42。这就是为什么eofbit
不会在输入流布尔转换运算符中起作用的原因。在下一次对流提取运算符>>的调用时,基础机器很快就会看到eofbit
已设置。这很快导致设置failbit
。
为什么第一段代码总是无法正常工作?
因为您不应该将EOF作为循环条件进行检查。循环条件应表示您要执行的操作,例如,从流中提取数字。