4

文字列に含まれる正規表現の一致数を調べようとしています。イテレータを使用して一致を反復し、整数を使用して一致数を記録しています。

long int before = GetTickCount();
string text;

boost::regex re("^(\\d{5})\\s(\\d{8})\\s(.*)\\s(.*)\\s(.*)\\s(\\d{8})\\s(.{1})$");
char * buffer;
long length;
long count;
ifstream f;


f.open("c:\\temp\\test.txt", ios::in | ios::ate);
length = f.tellg();
f.seekg(0, ios::beg);

buffer = new char[length];

f.read(buffer, length);
f.close();

text = buffer;
boost::sregex_token_iterator itr(text.begin(), text.end(), re, 0);
boost::sregex_token_iterator end;

count = 0;
for(; itr != end; ++itr)
{
    count++;
}

long int after = GetTickCount();
cout << "Found " << count << " matches in " << (after-before) << " ms." << endl;

私の例では、一致を表示するためにコードを for ループに入れても (そしてたくさんあります)、count は常に 1 を返します。何故ですか?私は何を間違っていますか?

編集

テスト入力:

12345 12345678 SOME NAME SOMETHING 88888888 N
12345 12345678 SOME NAME SOMETHING 88888888 N
12345 12345678 SOME NAME SOMETHING 88888888 N
12345 12345678 SOME NAME SOMETHING 88888888 N
12345 12345678 SOME NAME SOMETHING 88888888 N
12345 12345678 SOME NAME SOMETHING 88888888 N
12345 12345678 SOME NAME SOMETHING 88888888 N
12345 12345678 SOME NAME SOMETHING 88888888 N
12345 12345678 SOME NAME SOMETHING 88888888 N
12345 12345678 SOME NAME SOMETHING 88888888 N
12345 12345678 SOME NAME SOMETHING 88888888 N
12345 12345678 SOME NAME SOMETHING 88888888 N
12345 12345678 SOME NAME SOMETHING 88888888 N

出力 (一致なし):

16 ミリ秒で 1 件の一致が見つかりました。

for ループを次のように変更すると:

count = 0;
for(; itr != end; ++itr)
{
    string match(itr->first, itr->second);
    cout << match << endl;
    count++;
}

これを出力として取得します:

12345 12345678 SOME NAME SOMETHING 88888888 N
12345 12345678 SOME NAME SOMETHING 88888888 N
12345 12345678 SOME NAME SOMETHING 88888888 N
12345 12345678 SOME NAME SOMETHING 88888888 N
12345 12345678 SOME NAME SOMETHING 88888888 N
12345 12345678 SOME NAME SOMETHING 88888888 N
12345 12345678 SOME NAME SOMETHING 88888888 N
12345 12345678 SOME NAME SOMETHING 88888888 N
12345 12345678 SOME NAME SOMETHING 88888888 N
12345 12345678 SOME NAME SOMETHING 88888888 N
12345 12345678 SOME NAME SOMETHING 88888888 N
12345 12345678 SOME NAME SOMETHING 88888888 N
12345 12345678 SOME NAME SOMETHING 88888888 N
Found 1 matches in 47 ms.
4

4 に答える 4

12

ふふ。あなたの問題はあなたの正規表現です。(.\*)sをsに変更します(.\*?)(サポートされていると仮定します)。各行が一致しているように見えますが、実際には、パターンが貪欲であるため、テキスト全体が一致していることがわかります。

示されている問題を確認するには、ループ内のデバッグ出力を次のように変更します。

cout << "[" << match << "]" << endl;
于 2009-03-11T18:25:45.903 に答える
0

入力と出力を貼り付けることができますか?

countが1を返す場合、それは文字列に一致するものが1つしかないことを意味しますtext

于 2009-03-11T18:21:49.920 に答える
0

ブーストについてはよくわかりませんが、(end - itr) は機能しますか?

于 2009-03-11T18:30:06.407 に答える
0

結果を出力してもカウントは 1 のままであると言っているので、診断に役立ついくつかのことを調べることができます。

  • ループの反復ごとに count を出力してみて、何が起こるかを確認してください。これが 1 回しか出力されない場合、ループは 1 回しか実行されておらず、複数の一致だと思っていたものが、実際には 1 つの大きな長い一致でした。
  • それが機能する場合は、完全に別の変数名を使用してみてください。複数のcount変数を宣言した場所で、スコープ シャドーイングが発生している可能性があります。

そのループが複数回実行されている場合、問題はブーストの使用方法ではありません。何をしていても、boost には、渡さない変数を変更する機能はありません。(もちろん、countどこかを後押しするためにパスしている場合は、別の可能性があります。)

おそらく、最初(.*)に行うのは、入力のほぼ最後まですべてを一致させることです (改行を含む)。それらを (スペース以外のものに置き換えてみてください([^ ]*)。そうすれば、スペースが見つかるとマッチングが停止します。

于 2009-03-11T18:34:14.680 に答える