0

C++、、、ifstreamおよびテキスト ファイルを使用しています。n行末から文字を読み取る必要があるため、各行末の位置を探しています。

現在、すべてのバイトを読み取り、それが Unix の改行文字 (LF) に対応しているかどうかをテストしています。

残念ながら、入力は通常長いテキストであり、私の方法は高速ではありません。

より速い方法はありますか?

4

6 に答える 6

6

生の速度を探している場合は、ファイルをメモリマップし、次のようなものを使用strchrして改行を見つけます。

p = strchr(line_start, '\n');

pそうでない限り、NULLまたはメモリ領域の最初の文字である限りp[-1]、改行の前の文字を読み取るために使用できます。

注:ファイルに'\0'文字が含まれる可能性がある場合は、 memchr. 実際、バッファ (メモリ領域) のサイズを指定できるため、これは望ましい場合があります。

于 2012-03-08T16:03:03.953 に答える
2

私は C++、ifstream、およびテキスト ファイルを扱っています。行末から n 文字を読み取る必要があるため、各行の終わりの位置を探しています。

あなたの質問ではなく、行末から「n」文字を読んで、あなたの要件に焦点を当てます。

// Untested.
std::string s;
while(std::getline(std::cin, s)) {
    if(s.size() > n) s.erase(s.begin(), s.end()-n);
    // s is the last 'n' chars of the line
    std::cout << "Last N chars: " << s << "\n";
}
于 2012-03-08T16:25:36.540 に答える
1

のgetline関数を見てくださいstd::string。一度に 1 行全体を読み取ってから、文字列の末尾から文字を読み取ってください。

パフォーマンスの問題でよくあることですが、本当の秘訣は、コードをプロファイラーで実行して、コードがどこで時間を費やしているかを確認することです。多くの場合、「最速」と「十分に速い」の間には非常に大きな違いがあります。

于 2012-03-08T16:02:19.407 に答える
1

ライン マーカーの末尾に到達する簡単な方法はありませんが、データを読み取るときに読み取った内容を保存することで、時間を節約できます。戻る必要はなく、ループは非常に高速になります。

size の文字配列を作成し、nそれを循環バッファーとして使用します。配列の末尾に到達したら、先頭に戻るだけです。文字を循環バッファーの次の位置に格納します。

を検出する'\n'と、バッファーにはn前の文字が含まれていますが、順序が少しずれているだけです。プレフィックスはバッファー ポインターから始まり、バッファーの最後まで続き、サフィックスはゼロから始まり、バッファー ポインターから 1 を引いたところまで続きます。

これを機能させる方法の例を次に示します ( n== 20 と仮定):

int main()
{
    ifstream fs("c:\\temp\\a.txt");
    char buf[20];
    int bp = 0;
    bool circular = false;
    while (fs.good()) {
        char ch = fs.get();
        if (ch != '\n') {
            buf[bp] = ch;
            bp = (bp+1) % 20;
            circular |= !bp;
        } else {
            string s;
            if (circular) {
                s = string(buf+bp, buf+20) + string(buf, buf+bp);
            } else {
                s = string(buf, buf+bp);
            }
            cerr << s << endl;
            circular = false;
            bp = 0;
        }
    }
    return 0;
}
于 2012-03-08T16:11:13.450 に答える
0

クイック&ダーティな方法は、これらの行に沿ったものです:

ifs.seekg( 0, std::ifstream::end );
std::string buffer( ifs.tellg(), '\0' );
ifs.seekg( 0, std::ifstream::beg );
ifs.read( &buffer[0], buffer.size() );

次に、代わりにバッファで作業します。これにより、おそらく必要なすべての速度が向上します(私の経験では何桁も桁違いです)。任意に大きなファイルを処理できるようにしたい場合は、ロジックを少し変更する必要があります (代わりにチャンクで検索します)。

于 2012-03-08T16:10:07.180 に答える
0

何をしても、ファイルを直線的に検索することになります。検索は速くなるかもしれませんが、それでも線形検索になります。

本当の解決策は、ファイルの形式を変更することです。これにより、「興味深い」文字のインデックスがファイルの先頭近くに書き込まれます。それを読む時が来たら、ファイルの「興味のない」部分を完全にスキップできます。

それが不可能な場合は、別の「インデックス」ファイルを生成できる場合があります。これにより、線形検索を 1 回実行する必要がなくなるわけではありませんが、同じファイルに対して繰り返し実行する必要がなくなります。もちろん、これは同じファイルを複数回処理する場合にのみ重要です。

ところで、線形スキャンでさえかなり高速なはずです。何よりも I/O バウンドであるべきです。ファイルのサイズと、「私の方法は高速ではありません」とはどういう意味ですか?

于 2012-03-08T16:13:52.400 に答える