0

当我运行以下代码并编写例如“Peter”时,结果是我在文件中得到“Peter Peter”。

为什么?

#include "stdafx.h"
#include "iostream"
#include "iomanip"
#include "cstdlib"
#include "fstream"
#include "string"

using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
    ofstream File2;
    File2.open("File2.dat",ios::out);

    string name;
    cout<<"Name?"<<endl;
    while(!cin.eof())
    {
        cin>>name;
        File2<<name;
    }
    return 0;
}

当我将 while 循环更改为

while(cin>>name)
{
    File2<<name;
}

有用。但我不明白为什么第一种方法没有。

我无法回答我自己的问题(因为我没有足够的声誉)。因此,我在这里写下我的答案:

啊啊啊!!!好,谢谢。现在我明白了^^

我一直在测试

    while(!cin.eof())
{
    cin>>name;
    File2<<name;
    cout<<j++<<"cin.eof() "<<cin.eof()<<endl;
}

发生的情况是,当我提示crtl+z时,他仍处于 while 循环中。变量名称保持不变,并在下一行代码中添加到“File2”中。

以下是有效的:

while(!cin.eof())
{
    cin>>name;
    if(!cin.eof()){File2<<name;}
    cout<<j++<<"cin.eof() "<<cin.eof()<<endl;
}
4

2 回答 2

4

哼哼,这是被问到的第一百万次。这是错误的

while(!cin.eof())
{
    cin>>name;
    File2<<name;
}

eof()不做你认为它做的事。你认为它会告诉你你是否在文件的末尾,对吧?

eof()实际上所做的是告诉您为什么上次阅读失败。因此,这是您在读取后调用以查看失败原因的操作,而不是您在读取之前执行的操作以查看它是否会失败。eof()上次读取未失败时的返回值更复杂。这取决于您阅读的内容以及阅读方式。您正在尝试eof()在没有失败的情况下使用,因此结果可能会有所不同。

简短的回答是不要那样做,那样做

while(cin >> name)
{
    File2<<name;
}

顺便说一句,很抱歉语气轻率,我很想知道你为什么一开始就写错了代码。我们一直看到这个错误,似乎几乎每个新手都会犯同样的错误,所以我有兴趣了解这个错误来自哪里。您是否在其他地方看到过该代码,是否有人教您编写该代码,是否对您来说似乎正确等等。如果您能解释一下您的情况,我将不胜感激。

于 2013-09-21T08:38:49.647 回答
1

在循环条件中使用的基本问题std::cin.eof()是它在尝试从流中读取任何内容之前测试流状态。此时,流不知道将尝试读取什么,也无法预测将尝试什么。基本的见解是:你总是要在读取数据验证读取数据是否成功!

第二个问题是eof()只测试多个错误条件之一。std::string如果没有更多数据,读取 a只会出错,但对于大多数其他数据类型,也会出现格式失败。例如,int由于格式不匹配,读取 an 可能会出错。在这种情况下,std::ios_base::failbit将设置并在继续返回fail()true返回。eof()false

测试流本身等同于检测fail()流是否有问题的测试(它实际上还测试流是否为bad())。因此,读取文件的规范方法通常具有以下形式之一:

while (input) {
     // multiple read operations go here
     if (input) {
         // processing of the read data goes here
     }
}

或者

while (/* reading everything goes here */) {
    // processing of the read data goes here
}

显然,您可以使用for-loop 而不是while-loop。另一种有趣的读取数据的方法是使用std::istream_iterator<T>并假设 type 有一个输入运算符T。例如:

for (std::istream_iterator<std::string> it(std::cin), end; it != end; ++it) {
    std::cout << "string='" << *it << "'\n";
}

eof()在主阅读循环中没有使用这些方法。但是,eof()在循环之后使用来检测循环是否因为到达文件末尾或因为有一些格式错误而停止是合理的。

于 2013-09-21T09:28:04.830 回答