0

コードにバグがあります(質問の最後のコード)。私の C++ 実行可能ファイルの目的は、数値を含むファイルを読み取り、それを std::vector にコピーしてから、内容を stdout に出力することですか? 問題はどこだ?(あとい?)

次の数字を含む単純なテキスト ファイルがあります (各行に 1 つの数字があります)。

mini01:algorithms ios$ cat numbers.txt 
1
2
3
4
5

プログラムを実行すると、もう 1 行表示されます。

mini01:algorithms ios$ ./a.out 
1
2
3
4
5
0

stdout に 6 行目が表示されるのはなぜですか?

#include <iostream>
#include <string>
#include <fstream>
#include <vector>
using namespace std;

void algorithm(std::vector<int>& v) {

    for(int i=0; i < v.size(); i++) {
        cout << v[i] << endl;
    }

}

int main(int argc, char **argv) {

    string line;
    std::vector<int> vector1;
    ifstream myfile("numbers.txt");
    if ( myfile.is_open()) {
        while( myfile.good() )
        {
            getline(myfile, line);
            vector1.push_back(atoi(line.c_str()));
        }
        myfile.close();
    }
    else {
        cout << "Unable to open file" << endl;
    }

    algorithm(vector1);

    return 0;

}
4

4 に答える 4

6

を使用while (myfile.good())しないでください。1 回から複数回ループするからです。

代わりに使用

while (getline(...))

フラグを使用してループをチェックできない理由は、入出力操作が問題 (エラーまたはファイルの終わり) に気付くまでフラグが設定されないためです。

于 2013-04-10T13:07:28.193 に答える
2

good()抽出ループの条件として使用しないでください。次の読み取りが成功するかどうかを正確に示すものではありません。呼び出しをgetline条件に移動します。

while(getline(myfile, line))
{
    vector1.push_back(atoi(line.c_str()));
}

この特定のケースで失敗する理由は、通常、テキスト ファイル\nの末尾に があるためです (テキスト エディターでは表示されません)。最後の行が読み取られると、これ\nがストリームから抽出されます。はい、それはファイルの最後の文字かもしれgetlineませんが、\n抽出された . 終わった。good()EOF フラグを設定したり、 false を返す原因となるようなことをしたりしません。

そのため、次の反復でgood()is still true、ループが続行getlineされ、ファイルからの抽出が試行されます。ただし、抽出するものは何も残っておらずline、空の文字列に設定されるだけです。これは に変換されてintにプッシュされvector1、追加の値が得られます。

実際、抽出に問題があるかどうかを確認する唯一の確実な方法は、抽出にストリームのステータス ビットを確認することです。これを行う最も簡単な方法は、抽出自体を条件にすることです。

于 2013-04-10T13:07:59.413 に答える
1

C++ の素晴らしい世界へようこそ。最初にバグに進む前に、std::名前空間の解決を削除してから、vectorすでに持っている a を定義または宣言することをお勧めします。

using namespace::std;

2 番目のアドバイスは、実行可能な場所++iではなく、プリインクリメント演算子を使用することです。i++詳細については、こちらをご覧ください。

それ自体の問題になると、問題はファイルの最後に読み取られる空の新しい行です。これを回避する簡単な方法は、使用する前に行の長さを確認することです。

getline(myfile, line);
if (line.size()) {
  vector1.push_back(atoi(line.c_str()));
}

これにより、プログラムは空行が散在するファイルを読み取ることができるようになります。さらに確実にするために、atoi を使用する前に、読み取った行に数字以外の文字が含まれていないかどうかを確認できます。ただし、前述の最善の解決策は、ループ評価に読み取られた行を読み取るために使用することです。

于 2013-04-10T13:30:12.217 に答える
1

while「悪い読み取り」を行った後、条件が falseであるため、1 行読みすぎています。

于 2013-04-10T13:07:42.877 に答える