2017-04-26 7 views
3

単語、数字、特殊文字を含む文字列内にトークンを見つけようとしています。私は、次のコードを試してみました:特殊文字を含む正規表現を使用してC++文字列をトークン化

#include <iostream> 
#include <regex> 
#include <string> 
using namespace std; 
int main() { 
    string str("The ,quick brown. fox \"99\" named quick_joe!"); 
    regex reg("[\\s,.!\"]+"); 
    sregex_token_iterator iter(str.begin(), str.end(), reg, -1), end; 
    vector<string> vec(iter, end); 
    for (auto a : vec) { 
     cout << a << ":"; 
    } 
    cout << endl; 
} 

をそして次の出力ました:

The:quick:brown:fox:99:named:quick_joe: 

をしかし、私は出力を望んでいた:

私はそのために使用する必要がありますどのような正規表現
The:,:quick:brown:.:fox:":99:":named:quick_joe:!: 

?可能であれば、私は標準のC++に固執したいと思います。すなわち、私はブーストのあるソリューションが気に入らないでしょう。

(この質問のJavaのバージョンの43594465を参照してください、しかし、今、私はC++ソリューションを探しています。だから、基本的に、問題はC++にJavaのマッチャーとパターンをマッピングする方法である。)

+0

あなたの現在の正規表現の問題は、あなたが分割したいすべての可能な特殊文字を欠いています。文字クラスにすべてを追加するか、Jeffのコードで 'reg(R"(\ s *(\ W)\ s *) ")'を使用する必要があります(すべてのUnicode文字/数字がここで問題にならない場合)。鉱山とジェフのアプローチはASCII入力のみでOKです。 –

答えて

3

(部分マッチ-1)若干異なっている全マッチした部分文字列(部分マッチ0)、と:

sregex_token_iterator iter(str.begin(), str.end(), reg, {-1,0}), end; 

この利回り:

The: ,:quick: :brown:. :fox: ":99:" :named: :quick_joe:!: 

空白を削除するには、周囲の空白を消費する正規表現を変更し、空白以外の文字の取り込みグループを追加します。その後、だけではなく、部分マッチ0で、イテレータに部分マッチ1を指定します。

regex reg("\\s*([,.!\"]+)\\s*"); 
sregex_token_iterator iter(str.begin(), str.end(), reg, {-1,1}), end; 

収量:

The:,:quick brown:.:fox:":99:":named quick_joe:!: 

を隣接する単語の間にスペースを分割するとただのスペース "あまりにも上の分裂を必要とします。

regex reg("\\s*\\s|([,.!\"]+)\\s*"); 

ただし、空のサブセットで終了します:

それらをドロップするのに十分な簡単
The:::,:quick::brown:.:fox:::":99:":named::quick_joe:!: 

:最後に

regex reg("\\s*\\s|([,.!\"]+)\\s*"); 
sregex_token_iterator iter(str.begin(), str.end(), reg, {-1,1}), end; 
vector<string> vec; 
copy_if(iter, end, back_inserter(vec), [](const string& x) { return x.size(); }); 

The:,:quick:brown:.:fox:":99:":named:quick_joe:!: 
+0

詳細な回答ありがとうございます。 C++正規表現に関する良いチュートリアルとドキュメントがあるリンクを教えてください。 – R71

+0

私の主なリソースは次のとおりです:http://www.cplusplus.com/reference/regex/ –

+0

検索したところ、Marc Gregoire著、第2版14章の本「Professional C++」がこのトピック。 – R71

1

あなたがしたい場合はJava関連の質問で使用されている手法を使用してください。ここでもというアプローチに一致するを使用してください。

regex reg(R"(\d+|[^\W\d]+|[^\w\s])"); 
sregex_token_iterator iter(str.begin(), str.end(), reg), end; 
vector<string> vec(iter, end); 

C++ demoを参照してください。結果:The:,:quick:brown:.:fox:":99:":named:quick_joe:!:。これは、\w\dおよび\sも)のUnicode文字は、std::regexではUnicode対応ではないことに注意してください。

パターンは詳細: - 1桁以上

  • | - または
  • [^\W\d]+ - 1以上のASCII文字または_
  • | - または
  • [^\w\s]

    • \d+を - ASCII文字/ di以外の1文字git、_と空白。あなたが非マッチした部分文字列をインターリーブする求めている
  • +1

    あなたの答えとあなたのコメントに感謝します。両方の答えは正しいので、私は最初のものを受け入れました。 – R71

    関連する問題