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

问题描述:

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

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

ifstream inFile; 
ofstream outFile; 
string laastName; 
string firstName; 
double salary; 
double percent; 
double new Salary; 
double increase; 

inFile.open("Ch3_Ex6Data.txt"); 
outFile.open("Ch3_Ex6Output.dat"); 

while(!inFile.eof()) { 

    inFile >> lastName; 
    inFile >> firstName; 
    inFile >> salary; 
    inFile >> percent; 

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

    outFile << firstName << " " << lastName << " "; 
    outFile << setprecision(2) << fixed << newSalary << endl; 

} 

inFile.close(); 
outFile.close(); 

return 0 
} 

输出文件

Andrew Miller 69079.36 
Sheila Green 82722.89 
Amit Sethi 79469.43 
Amit Sethi 74946.19 

我的问题是,为什么是最后一行获得输出两次,为什么它比第一个不同?我不明白为什么循环继续。文件标记的结尾是否不打?我能够通过放入一个索引变量并在while循环中放入第二个条件来对其进行硬编码,通过说& &小于索引,但我感觉好像我不应该那样做。

+5

臭名昭著',而(!inFile.eof()){'错误! –

+0

你可以使用这个:'while(inFile >> lastName >> firstName >> salary >> percent)'{} – Raindrop7

  • 您使用lastName但你申报laastName所以去除a和谨慎。

  • double new Salary:这是什么? - 我认为你的意思是:double NewSalary如果是这样,请阅读一本关于在C++中命名变量的有用书,因为你故意搞砸了。

  • while(!inFile.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; 
    } 
    

您不检查是否有读取成功。你输出的东西是否读取失败。

您的代码似乎预计eof()可以预测未来的阅读是否会成功。但它并不能预测未来。未来的阅读仍然会失败。

上一次通过循环,所有的读取操作失败,所以所有的变量仍然有它们的原始值。然后再输出最后一行。然后你最后检查错误(呼叫eof()在循环中的时间),但它为时已晚。

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

顺便说一句,这是一个非常常见的错误,出现在许多不同的环境中。这个错误的关键在于你试图检查所有必要的条件,以便成功,然后假设事情会成功,因为你检查了它可能会失败的每一个方式。至少有三个原因,这是一个糟糕的主意。首先,这通常是浪费精力。其次,当您检查和尝试操作时,事情可能会发生变化。第三,你可能错过了其中一种失败的方式。

在这里,所有三个原因适用。

+0

它保留了前一次迭代的值。 –

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

这意味着完成读取文件的最后一行确实是而不是设置文件结束位,而eof()仍然是错误的。因此你的程序运行到下一个循环周期,并进行后,才在该行

inFile >> lastName; 

下一个读操作,eofbit被设定。 最后一行打印两次,因为上一次循环迭代过程中的所有读取操作都会失败,并且变量仍然具有前一次循环迭代的值。

编辑: 为了防止您可以检查读取操作是否成功,例如,通过在循环中使用inFile.good()

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; 
} 

的问题是,eof没有做什么,你认为它。

想象一下,你在地板上行走,铺瓷砖后,拿起地板上的东西,放在你的口袋里,露出(打印)你口袋里的内容。

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

eof然后,告诉你你的鼻子何时坏了,而不是当瓷砖是最后的时候。

所以,你在最后一块瓷砖上,检查一下你的鼻子,找到它,然后向前走一步。你的鼻子现在流血了,没有什么可以偷看到我们的口袋里,而你的口袋里仍然包含着......他们以前的东西。

您打印口袋的内容(再次),并检查您的鼻子。它坏了:你退出。

来解决这个问题的习惯的方法是这样的一个:

while(inFile >> lastName 
      >> firstName 
      >> salary 
      >> percent) 
{ 
    //all your computation here 
} 

我觉得你应该自己为什么理解。