INPUT FILE
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循环来对其进行硬编码,方法是说&amp;&amp;低于指数,但我觉得我不应该做任何事情。
答案 0 :(得分:2)
您无法检查是否有任何读取成功。无论读取是否失败,您都可以输出内容。
您的代码似乎期望eof()
预测未来的读取是否会成功。但它并不能预测未来。未来的阅读仍然可能失败。
您最后一次循环,所有读取操作都失败,因此所有变量仍然具有原始值。然后再次输出最后一行。然后你最终检查错误(调用eof()
循环中的时间),但为时已晚。
相反,为什么不检查您的读取是否成功?这就是你真正想知道的。
顺便说一下,这是在许多不同背景下出现的一个非常常见的错误。错误的关键在于你试图检查成功所需的所有条件,然后假设事情会成功,因为你检查了它可能失败的每一种方式。至少有三个原因,这是一个坏主意。首先,它通常会浪费精力。其次,在您检查和尝试操作之间,事情可能会发生变化。第三,你可能错过了失败的方式之一。
这里有三个理由适用。
答案 1 :(得分:2)
问题在于eof
没有按照您的想法行事。
想象一下,你正走在地板上,瓷砖铺贴瓷砖,拿起地板上的东西,把它放在口袋里,然后出现(打印)你的口袋内容。
当你把脚放在最后一块瓷砖上时,地板还没有“结束”,你的鼻子仍然是安全的。你还没有(还)砸墙。你填满口袋并打印出来。
然后, eof
会告诉你鼻子什么时候坏了,而不是当瓷砖是最后一块时。
所以,你在最后一块瓷砖上,检查你的鼻子,发现它没问题,向前走一步。你的鼻子现在正在流血,没有东西可以偷看我们的口袋里,你的口袋里还装着......以前的东西。
你打印口袋的内容(再一次),然后检查你的鼻子。它坏了:你退出了。
解决这个问题的惯用方法是:
while(inFile >> lastName
>> firstName
>> salary
>> percent)
{
//all your computation here
}
我认为你应该自己理解为什么。
答案 2 :(得分:1)
当输入操作到达流的末尾时,eofbit不会被设置(如:读取最后一行),但是当输入操作尝试在流结束后读取数据时(如:当没有剩余数据时读取数据,因为已经到达文件流的末尾。)
这意味着完成读取文件中的最后一行不设置文件结束位,eof()
仍为false。因此,您的程序将进入下一个循环迭代,并且仅在下一行读取
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;
}
答案 3 :(得分:0)
您使用了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;
}