C++、、、ifstream
およびテキスト ファイルを使用しています。n
行末から文字を読み取る必要があるため、各行末の位置を探しています。
現在、すべてのバイトを読み取り、それが Unix の改行文字 (LF) に対応しているかどうかをテストしています。
残念ながら、入力は通常長いテキストであり、私の方法は高速ではありません。
より速い方法はありますか?
C++、、、ifstream
およびテキスト ファイルを使用しています。n
行末から文字を読み取る必要があるため、各行末の位置を探しています。
現在、すべてのバイトを読み取り、それが Unix の改行文字 (LF) に対応しているかどうかをテストしています。
残念ながら、入力は通常長いテキストであり、私の方法は高速ではありません。
より速い方法はありますか?
生の速度を探している場合は、ファイルをメモリマップし、次のようなものを使用strchr
して改行を見つけます。
p = strchr(line_start, '\n');
p
そうでない限り、NULL
またはメモリ領域の最初の文字である限りp[-1]
、改行の前の文字を読み取るために使用できます。
注:ファイルに'\0'
文字が含まれる可能性がある場合は、 memchr
. 実際、バッファ (メモリ領域) のサイズを指定できるため、これは望ましい場合があります。
私は 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";
}
のgetline関数を見てくださいstd::string
。一度に 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;
}
クイック&ダーティな方法は、これらの行に沿ったものです:
ifs.seekg( 0, std::ifstream::end );
std::string buffer( ifs.tellg(), '\0' );
ifs.seekg( 0, std::ifstream::beg );
ifs.read( &buffer[0], buffer.size() );
次に、代わりにバッファで作業します。これにより、おそらく必要なすべての速度が向上します(私の経験では何桁も桁違いです)。任意に大きなファイルを処理できるようにしたい場合は、ロジックを少し変更する必要があります (代わりにチャンクで検索します)。
何をしても、ファイルを直線的に検索することになります。検索は速くなるかもしれませんが、それでも線形検索になります。
本当の解決策は、ファイルの形式を変更することです。これにより、「興味深い」文字のインデックスがファイルの先頭近くに書き込まれます。それを読む時が来たら、ファイルの「興味のない」部分を完全にスキップできます。
それが不可能な場合は、別の「インデックス」ファイルを生成できる場合があります。これにより、線形検索を 1 回実行する必要がなくなるわけではありませんが、同じファイルに対して繰り返し実行する必要がなくなります。もちろん、これは同じファイルを複数回処理する場合にのみ重要です。
ところで、線形スキャンでさえかなり高速なはずです。何よりも I/O バウンドであるべきです。ファイルのサイズと、「私の方法は高速ではありません」とはどういう意味ですか?