簡體   English   中英

無緣無故讀取文件時跳過C ++行

[英]C++ line being skipped while reading a file for no reason

假設我正在讀取一個文件(具體來說是“ infile.txt”)來計算測驗分數的平均值。 正在讀取的文件如下:

塞巴斯蒂安·傑克(Sebastian Jack)40 50 60 72 39 67 85 10 92 83

里克丹48 19 2 3 29 10 60 72 83 91

Yao耀48 30 68 27 94 81 20 38 90 81

甲板豪91 82 65 55 79 93 89 19 23 37

通過將另一個int數加到另一個文件中,該整數是每個學生的平均分數。 但是,第二和第四名學生無緣無故被跳過。 這是輸出:

塞巴斯蒂安·傑克(Sebastian Jack)40 50 60 72 39 67 85 10 92 83 59.8

Yao耀48 30 68 27 94 81 20 38 90 81 57.7

這是我的代碼:

// This is a program that will output the average quiz score of all student,
based on the student score file

#include <iostream>
#include <fstream>
#include <string>

int main()
{
    using namespace std;

    ifstream inf;
    ofstream outf;

    inf.open("infile.txt");
    outf.open("outfile.txt");

    string name;
    int score, total;
    double average;
    char next;
    while (inf >> name) {
        total = 0;

        outf << name << ' ';
        inf >> name;
        outf << name << ' ';

        while (inf >> score) {
            total += score;
            outf << score << ' ';
        }
        average = total / 10.0;
        outf << average << endl;

        inf.clear();
        inf.ignore(numeric_limits<streamsize>::max(), '\n');
    }

    inf.close();
    outf.close();
    return 0;
}

有沒有我的代碼的任何錯誤? 非常感謝!

Jaspreet的建議是正確的。 我將為其添加一些背景。

您的程序邏輯是讀取數據的一種有效方法。 (另一種可能性,對於面向行的數據“記錄”通常更直觀,是逐行讀取並逐行解析,這使得每條“記錄”的結尾都很明顯。)

現在,為什么ignore()跳過行? 原因是此時空行已被跳過。 詳細:

您的算法會嘗試讀取數字,直到由於下一個單詞沒有數字(或到達EOF)而失敗為止。 現在,讀取數字的庫邏輯從跳過任何前導空格(包括換行符)開始; 您現在看到了問題。 只有在讀取了姓氏的第一個字母之后,數字讀取算法才會放棄並將讀取的字母放回輸入中。 跳過的換行符不會退回。 然后,您將ignore並跳過我們開頭的有效行。

好消息是,對於記錄的內部結構表示記錄邊界的記錄(如此處:記錄以一系列數字結尾;第一個非數字表示新記錄的開頭),您可以忽略任何空白,例如換行符並進行解析逐詞地。 這使程序更加健壯:您可以處理沒有空行,沒有多個空行或根本沒有任何換行符的數據!

盡管可以想象,盡管數據可能偶爾包含錯誤(例如,數字中的字母),但在進行健壯編程的過程中,仍可以將換行符用作嘗試重新同步的位置。 但是,在您的情況下,重新同步將自動發生(可能是在讀取了一個錯誤解析的“記錄”后,其中的名字帶有數字)。

作為最后的討論,我建議使用這種類型的數據處理從stdin讀取並向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.
}

我認為函數ignore(numeric_limits<streamsize>::max(), '\\n'); 正在忽略,直到得到另一個'\\n' ,嘗試不使用它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM