while(!file.eof())和while(file >> variable)的区别是什么?

4

首先 - 我手头上有一个文本文件,其中包含二进制数字,每行一个数字。我想在C++程序中读取它们并将它们相加。我编写了一个函数,将它们转换为十进制数并在此之后将它们相加,我很确定这个函数是正确的。但是,对于这两种不同的读取文本文件的方式,我得到了不同的结果(只有其中一个结果是正确的)[我的函数是decimal()]:

ifstream file;
file.open("sample.txt");
int sum = 0;
string BinaryNumber;
while (!file.eof()){
    file >> BinaryNumber;
    sum+=decimal(BinaryNumber);
}

这样我的总和就太大了,但只差一个很小的数量。

ifstream file;
file.open("sample.txt");
int sum = 0;
string BinaryNumber;
while (file >> BinaryNumber){
    sum+=decimal(BinaryNumber);
}

通过这种方式,我得到了正确的总和。经过一些测试,我得出结论,使用eof()的while循环比另一个while循环多进行一次迭代。那么我的问题是 - 从文本文件中读取的这两种方法有什么区别?为什么第一个while循环给我错误的结果,它可能做了额外的迭代?


file >> variable 检查输入后的 file 状态。每当您输入错误或达到 EOF 时,条件为 false - πάντα ῥεῖ
你的第一个示例失败了,因为eof()返回先前读取操作的状态,并且直到你读取完流的末尾后才返回false。 - Captain Obvlious
2个回答

7
区别在于 >> 先读取数据,然后告诉您是否成功,而 file.eof() 在读取之前进行检查。这就是为什么使用 file.eof() 方法会多读取一次,并且该读取是无效的。
您可以通过将检查移动到读取后的位置来修改 file.eof() 代码,使其正常工作,如下所示:
// This code has a problem, too!
while (true) {            // We do not know if it's EOF until we try to read
    file >> BinaryNumber; // Try reading first
    if (file.eof()) {     // Now it's OK to check for EOF
        break;            // We're at the end of file - exit the loop
    }
    sum+=decimal(BinaryNumber);
}

然而,如果最后一个数据条目后面没有定界符,此代码将会出错。因此,你的第二种方法(即检查>>的结果)是正确的。
编辑:此帖子已根据this comment进行了编辑。

1
它们都检查eof吗,还是>>版本检查bad - user541686
2
@Mehrdad,>> 操作取决于您是否使用 C++11:在 C++11 之前,它调用 operator void*;从 C++11 开始,它调用 operator bool()链接)。 - Sergey Kalinichenko
1
实际上,在读取输入后检查eof()错误的!这次错误的方向相反:如果最后一个值后面没有跟着一个空格,它就不会被处理。唯一正确的方法是检查file的状态,即转换为布尔值或fail() - Dietmar Kühl
1
@dasblinkenlight:啊,好的,不过那不是我的重点。似乎布尔转换使用的是“fail”而不是“eof”,因此首先语义上并不完全相同。 - user541686
@DietmarKühl 感谢您的精彩评论!我没有意识到“修复”是有问题的(我在我的代码中使用了将转换为 bool/ void*,但我没有意识到中间的 eof 检查是有问题的)。我编辑了答案来解释这一点。 - Sergey Kalinichenko

2
当使用file.eof()进行输入测试时,最后一次输入可能会失败且值保持不变,因此会被处理两次:读取字符串时,流首先跳过前导空格,然后读取字符,直到找到空格为止。假设最后的值后面紧跟一个换行符,则流尚未触及EOF,即file.eof()不是true,但读取字符串失败,因为没有非空格字符。
当使用file >> value进行操作并检查其成功时:总是使用这种方法!使用eof()仅是为了确定读取失败是否是由于达到EOF或其他原因所致。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接