C++ 为什么输入文件的最后一行运行了两次?

C++ 为什么输入文件的最后一行运行了两次?,c++,file-io,while-loop,eof,C++,File Io,While Loop,Eof,输入文件 Miller Andrew 65789.87 5 Green Sheila 75892.56 9 Sethi Amit 74900.50 6.1 我的问题是,为什么最后一行得到两次输出,为什么它与第一行不同?我不明白为什么循环还在继续。文件结尾标记是否未命中?我可以通过输入一个索引变量来硬编码它,并在while循环中输入第二个条件,即&&less-than-index,但我觉得我似乎不应该这样做 不检查任何读取是否成功。无论读取是否失败,都可以输出内容 您的代码似乎期望eof()预

输入文件

Miller Andrew 65789.87 5
Green Sheila 75892.56 9
Sethi Amit 74900.50 6.1


我的问题是,为什么最后一行得到两次输出,为什么它与第一行不同?我不明白为什么循环还在继续。文件结尾标记是否未命中?我可以通过输入一个索引变量来硬编码它,并在while循环中输入第二个条件,即&&less-than-index,但我觉得我似乎不应该这样做

不检查任何读取是否成功。无论读取是否失败,都可以输出内容

您的代码似乎期望
eof()
预测将来的读取是否会成功。但它不能预测未来。未来的读取仍然可能失败

上次通过循环时,所有读取操作都失败,因此所有变量仍保留其原始值。然后再次输出最后一行。最后检查错误(调用
eof()
循环中的时间),但为时已晚

相反,为什么不检查您的读取是否成功?这才是你真正想知道的

顺便说一下,这是一个非常常见的错误,出现在许多不同的情况下。错误的症结在于你试图检查某件事成功的所有必要条件,然后假设该事会成功,因为你检查了它可能失败的所有方式。这是一个坏主意,至少有三个原因。首先,这通常是白费力气。第二,检查和尝试操作之间可能会发生变化。第三,你可能错过了它可能失败的方式之一


在这里,这三个原因都适用。

当输入操作到达流的结尾时(如:读取最后一行),但当输入操作尝试在流的结尾后读取数据时(如:在没有更多数据时尝试读取数据,因为已到达文件流的结尾),不会设置eofbit

这意味着完成读取文件中的最后一行不会设置文件结尾位,并且
eof()
仍将为false。因此,您的程序将运行到下一个循环迭代中,并且仅在该行中的下一次读取之后运行

inFile >> lastName;
执行时,设置eofbit。 最后一行打印两次,因为上一次循环迭代期间的所有读取操作都失败,并且变量仍然具有上一次循环迭代的值

编辑: 为了防止出现这种情况,您可以检查读取操作是否成功,例如通过在循环中使用:

while(!inFile.eof()) {
    inFile >> lastName;
    inFile >> firstName;
    inFile >> salary;
    inFile >> percent;

    //check whether no errors occurred during the input operations
    if (!inFile.good())
    {
      //input failure, leave the loop
      break;
    }

    percent /= 100;
    increase = salary * percent;
    newSalary = increase + salary;

    outFile << firstName << " " << lastName << " ";
    outFile << setprecision(2) << fixed << newSalary << endl;  
}
while(!infle.eof()){
填充>>姓氏;
填充>>名字;
填写>>工资;
填充>>百分比;
//检查输入操作期间是否没有发生错误
如果(!infle.good())
{
//输入失败,退出循环
打破
}
百分比/=100;
增加=工资*百分比;
新工资=增加+工资;

outFile问题在于,
eof
并没有做你认为它做的事情

想象你在地板上行走,一块接一块地,捡起地板上的东西,把它放进口袋,然后展示(打印)你口袋里的内容

当你把脚放在最后一块瓷砖上时,地板还没有“结束”,你的鼻子仍然安全。你还没有(还)撞墙。你把口袋装满,然后打印出来

eof
则会告诉你鼻子什么时候断了,而不是最后一块瓷砖什么时候断了

所以,你在最后一块地砖上,检查你的鼻子,发现没问题,然后向前走一步。你的鼻子现在在流血,没有东西可以偷看放在我们的口袋里,你的口袋里仍然装着…他们以前有的东西

你(再一次)打印口袋里的东西,然后检查你的鼻子。它坏了:你退出

解决这个问题的惯用方法是:

while(inFile >> lastName
             >> firstName
             >> salary
             >> percent)
{
   //all your computation here
}
我想你应该自己理解原因。

  • 您使用了
    lastName
    ,但声明了
    lastName
    ,因此请删除
    a
    ,并小心

  • < > >代码>双新工资<代码>:这是什么?-我想你的意思是:<代码>双Neal薪\ <代码>如果你故意故意搞乱,请阅读一本关于C++中变量命名的有用的书。< /P>
  • 但不建议使用(!infle.eof())
    ,因此请放弃使用它

  • main
    的末尾缺少分号

  • 您的代码如下所示:

    int main()
    {
        ifstream inFile;
        ofstream outFile;
        string lastName;
        string firstName;
        double salary;
        double percent;
        double newSalary;
        double increase;
    
        inFile.open("Ch3_Ex6Data.txt");
        outFile.open("Ch3_Ex6Output.dat");
    
        while(inFile >> lastName >> firstName >> salary >> percent){
            percent /= 100;
            increase = salary * percent;
            newSalary = increase + salary;
    
            outFile << firstName << " " << lastName << " ";
            outFile << setprecision(2) << fixed << newSalary << endl;
    
        }
    
        inFile.close();
        outFile.close();
    
        return 0;
    }
    
    intmain()
    {
    河流充填;
    出流孔的直径;
    字符串lastName;
    字符串名;
    双薪;
    百分之二;
    双新闻汇编;
    双倍增长;
    infle.open(“Ch3_Ex6Data.txt”);
    输出文件打开(“Ch3_Ex6Output.dat”);
    而(填写>>姓氏>>姓氏>>工资>>百分比){
    百分比/=100;
    增加=工资*百分比;
    新工资=增加+工资;
    
    outFile臭名昭著的
    while(!infle.eof()){
    bug!!!您可以使用这个:
    while(infle>>lastName>>firstName>>salary>>percent)
    {}并保留上一次迭代的值。
    while(inFile >> lastName
                 >> firstName
                 >> salary
                 >> percent)
    {
       //all your computation here
    }
    
    int main()
    {
        ifstream inFile;
        ofstream outFile;
        string lastName;
        string firstName;
        double salary;
        double percent;
        double newSalary;
        double increase;
    
        inFile.open("Ch3_Ex6Data.txt");
        outFile.open("Ch3_Ex6Output.dat");
    
        while(inFile >> lastName >> firstName >> salary >> percent){
            percent /= 100;
            increase = salary * percent;
            newSalary = increase + salary;
    
            outFile << firstName << " " << lastName << " ";
            outFile << setprecision(2) << fixed << newSalary << endl;
    
        }
    
        inFile.close();
        outFile.close();
    
        return 0;
    }