2

テキスト エディターでは同じように見える 2 つのテキスト ファイルがありますが、ファイルを読み取るための C++ コードでは、ファイルごとに異なる行数が生成されます。ファイルがどこで異なるのか、または C++ コードでそのような違いに対応する方法がわかりません。

説明させてください...

d1.txt と d2.txt の 2 つのテキスト ファイルがあります。それぞれに 1 行に 1 つずつ、100 個の数字が含まれています。いずれかのファイルを vim で開いて と入力すると:set list!、100 行しかなく、各行の最後の数字の後に数字と行末文字 ($) が含まれています。つまり、vim でそれらを見ると、数値の精度が異なることを除けば、同じように見えます。1 つのファイルは MATLAB からのもので、もう 1 つのファイルは Gnumeric からのものであるため、精度が異なります。

ファイルの簡単な diff は、次の出力をレンダリングします (私は中かっこの省略記号 "[...]" を使用して、スペースのために一部を省略しています)。

1,28c1,28
< 0.01218465532007
       [...]
< 0.01327976337895
---
> 0.0121846553200678
       [...]
> 0.0132797633789485
30,100c30,100
< 0.01329705254301
       [...]
< 0.00017832496354
---
> 0.0132970525430057
       [...]
> 0.000178324963543758
\ No newline at end of file

2 番目のファイル (d2.txt) の末尾に改行がないというメッセージが表示されますが、前述のように、vim でファイルの最後の行を調べても違いはわかりません。

readVectorFromFile(std::vector<double>&,const string)それぞれのテキスト ファイルから読み取った行数を返すC++ 関数を作成しました。コードを使用してテキスト ファイルを読み取ると、次のようになります。

std::cout << "d1.txt has " << readVectorFromFile(v1,"./d1.txt") << " lines.\n";
std::cout << "d2.txt has " << readVectorFromFile(v1,"./d1.txt") << " lines.\n";

出力が得られます:

d1.txt has 99 lines.
d2.txt has 100 lines.

関数は次のように定義されます。

int readVectorFromFile(vector<double>& vec, const string& fullFilePathName) {

    int value, numLines;
    char line[10000];
    ifstream inFile;

    /* attempt to open file */
    inFile.open(fullFilePathName.c_str());
    if (inFile.fail()) {
        LOG(FATAL) << "Unable to open file \"" << fullFilePathName.c_str() << "\" for reading.";
    } else {
        cout << "Importing vector from file " << fullFilePathName.c_str() << "\n";
    }

    /* records the number of lines in the input file */
    numLines = static_cast<int>( count(istreambuf_iterator<char>(inFile),
                                       istreambuf_iterator<char>(), '\n') );

    /* start file over from beginning */
    inFile.clear();
    inFile.seekg(0, ios::beg);

    vec.clear(); // clear current vec contents
    vec.reserve(numLines);

    /* read value from each line of file into vector */
    for(int i=0; i<numLines; ++i) {
        inFile.getline(line, 10000);
        vec.push_back( strtod(line,NULL) );
    }

    inFile.close(); // close filestream

    return numLines; // return the number of lines (values) read

}

これらのファイルを vim で表示すると、これらのファイルの違いがわからないのはなぜですか? この問題を引き起こしている上記の機能に根本的な問題はありますか?

4

1 に答える 1

2

あなたの説明に基づいて、2 つのファイルのうちの 1 つの末尾に改行がありません。od -c file | lessたとえば、文字コードを含むファイルの正確な内容を確認するために、を使用してファイルを見ることができます。

とはいえ、行を読み取るアプローチはおそらく改善される可能性があります。行を読み取って、読み取れるかどうかを確認し、処理するだけです。このように、前もって行末の数を数える必要はありません。

for (std::string line; std::getline(inFile, line); ) {
    vec.push_back(strtod(line.c_str()));
}

個人的には、おそらく最初に数字を読むだけでしょう。たとえば、次のようになります。

for (double value; inFile >> value; ) {
    vec.push_back(value);
}

doubleこれは s のシーケンスをベクトルに読み込む方法ではありませんが、次のようになります。

std::vector<double> vec((std::istream_iterator<double>(inFile)),
                        std::istream_iterator<double>());

(余分な括弧の代わりに、C++11 で統一された初期化表記を使用できます)。

于 2013-08-26T00:49:37.263 に答える