Jaspreet的建議是正確的;我會添加一些背景。
您的程序邏輯是讀取數據的一種有效方法。 (另一種可能性,對於面向行的「記錄」數據通常更直觀,是逐行讀取並單獨解析每行,這使得每個「記錄」的末尾顯而易見。)
現在爲什麼是ignore()
跳行?原因是空行已經被跳過了。詳細信息:
您的算法嘗試讀取數字,直到失敗,因爲下一個單詞不是數字(或因爲已達到EOF)。現在讀取數字的庫邏輯首先跳過任何主要的空白,包括換行符;你現在看到了問題。只有讀取下一個名字的第一個字母后,數字讀取算法纔會放棄,並將讀取的字母放回到輸入中。跳過的換行符不會退回。然後來到您的ignore
並跳過我們站在開頭的有效線。
好消息是,對於內部結構顯示記錄邊界(如:記錄以數字序列結束;第一個非數字表示新記錄開始處)的記錄,您可以忽略任何空白行打破並且一字一句地解析。這使程序更健壯:您可以在沒有空行或多空行的情況下處理數據,或根本沒有任何換行符!
如果儘管數據可能包含偶然錯誤(例如數字中的一個字母),但仍然可以將這些換行符用作可以嘗試重新同步的位置,這是通過強大的編程實現的。但在你的情況下,重新同步會自動發生(可能是在讀了一個嚴重分析過的「記錄」,其中有一個名字帶有一個數字)。
作爲最後討論細點,我建議從標準輸入讀取和寫入這種類型的數據處理到stdout;將數據源和目的地留給呼叫者(通過myprog <infile.txt> outfile.txt
等)。 Windows和* nix命令行都支持這一點。這使得該程序更加通用並且節省了編程工作。如果分配要求要讀取的兩個文件,對上述數據中分離的實際算法工作(解析記錄並計算平均值)從獲取和編寫數據,這應該是在剛得到一個IStream功能和ostream。這將使得可以通過任何來源提供數據,例如字符串,通過串流。
事實上,人們可以通過定義一個與數據記錄相對應的類,併爲它重載operator>>
,以及一個float record.averageScore()
成員函數:-)來分離算法工作。這看起來更像C++。
這裏有什麼可能工作幾個片斷。 playerT
是一個擁有「記錄」數據的類。我實現了輸入函數,因爲清除輸入流的失敗位有點棘手。
/// Currently just a first name, family name and vector of scores
class playerT
{
string firstName;
string lastName;
vector<float> scores;
public:
float averageScore()
{
return scores.size()
? accumulate(scores.begin(), scores.end(), 0.0)/scores.size()
: 0; // avoid dividing by zero.
}
friend ostream & operator<<(ostream &os, const playerT &player);
friend istream &operator>>(istream &is, playerT &player);
};
/// Produces output which could be read back with
/// the input operator. In particular, does not
/// output the average.
ostream &operator<<(ostream &os, const playerT &player)
{
//...
}
// Error handling is left to the caller.
// In particular, after EOF the player must be tested for completeness.
istream &operator>>(istream &is, playerT &player)
{
is >> player.firstName >> player.lastName;
player.scores.clear();
float nextScore;
while(is >> nextScore)
{
player.scores.push_back(nextScore);
}
// Clear the expected format error indicating end of scores
// (and therefore this record),
// but not others which must be handled by the caller.
is.clear(is.rdstate() & ~ios::failbit);
return is;
}
主要功能歸結爲很少,這使得信息流更清晰。原因是像清除失敗位等髒I/O細節被轉移到專門的功能,以及計算平均值的「業務邏輯」。
int main()
{
do // loop to eof
{
playerT newPlayer;
cin >> newPlayer;
// if this was the last record eof is now true
// and the loop will exit after printing the last record.
// todo: handle I/O errors
cout << newPlayer << " (Av.: " << newPlayer.averageScore() << ')' << endl;
}while(cin.good());
return cin.bad(); // eof is ok. only bad is bad.
}
「有我的代碼的任何錯誤?」是。考慮用'getline'來讀取單獨的行。你有一個squirrely while循環。 – AndyG
'忽略'每隔一行就扔掉。註釋,並寫出所有行。 – wally
如果您的代碼有效,您可能需要發送到[email protected] –