2009-05-21 12 views
4

私はブーストストリングライブラリを使って遊んでいて、スプリット方法のすばらしさを簡単に見つけました。素晴らしく、簡潔になりboost splitでescaped_list_separatorを使用する

string delimiters = ","; 
    string str = "string, with, comma, delimited, tokens, \"and delimiters, inside a quote\""; 
    // If we didn't care about delimiter characters within a quoted section we could us 
    vector<string> tokens; 
    boost::split(tokens, str, boost::is_any_of(delimiters)); 
    // gives the wrong result: tokens = {"string", " with", " comma", " delimited", " tokens", "\"and delimiters", " inside a quote\""} 

...しかし、それは引用符で動作するようには思えないし、代わりに私は、次の

string delimiters = ","; 
string str = "string, with, comma, delimited, tokens, \"and delimiters, inside a quote\""; 
vector<string> tokens; 
escaped_list_separator<char> separator("\\",delimiters, "\""); 
typedef tokenizer<escaped_list_separator<char> > Tokeniser; 
Tokeniser t(str, separator); 
for (Tokeniser::iterator it = t.begin(); it != t.end(); ++it) 
    tokens.push_back(*it); 
// gives the correct result: tokens = {"string", " with", " comma", " delimited", " tokens", "\"and delimiters, inside a quote\""} 
私の質問を分割することができますされ

または別のような何かをしなければなりません区切り文字を引用符で囲んだ場合は標準アルゴリズムを使用しますか? Purpledogに感謝しますが、私はすでに望ましい結果を達成するために廃止されていない方法を持っています。私はそれがかなり面倒だと思っています。それをよりシンプルで洗練されたソリューションに置き換えることができなければ、さらに別の方法。

EDIT:結果を表示し、質問を明確にするためのコードが更新されました。

答えて

5

ブースト:: splitメソッドを使用してこれを行うには任意の簡単な方法があることを思えません。私はこれを行うに見つけることができるコードの最短部分は、わずかに、より詳細なオリジナルのスニペットより

vector<string> tokens; 
tokenizer<escaped_list_separator<char> > t(str, escaped_list_separator<char>("\\", ",", "\"")); 
BOOST_FOREACH(string s, escTokeniser) 
    tokens.push_back(s); 

ある

vector<string> tokens; 
boost::split(tokens, str, boost::is_any_of(",")); 
2

boost :: stringライブラリについてはわかりませんが、boost regex_token_iteratorを使用すると、正規表現のデリミタを表すことができます。だから、引用符で区切られた区切り文字を使用することもできますし、はるかに複雑なものも使用できます。

これは以前は廃止されていたregex_splitで行われていたことに注意してください。ここで

は、ブーストドキュメントから取った例です:

#include <iostream> 
#include <boost/regex.hpp> 

using namespace std; 

int main(int argc) 
{ 
    string s; 
    do{ 
     if(argc == 1) 
     { 
     cout << "Enter text to split (or \"quit\" to exit): "; 
     getline(cin, s); 
     if(s == "quit") break; 
     } 
     else 
     s = "This is a string of tokens"; 

     boost::regex re("\\s+"); 
     boost::sregex_token_iterator i(s.begin(), s.end(), re, -1); 
     boost::sregex_token_iterator j; 

     unsigned count = 0; 
     while(i != j) 
     { 
     cout << *i++ << endl; 
     count++; 
     } 
     cout << "There were " << count << " tokens found." << endl; 

    }while(argc == 1); 
    return 0; 
} 

プログラムは引数としてのHello Worldで開始された場合、出力は次のようになります。

hello 
world 
There were 2 tokens found. 

ブースト::正規表現の再変更します( "\ s +");boost :: regex re( "\"、\ "");は引用符で区切られた区切り文字を分割します。 ハローでプログラムを起動する「」引数として世界もにつながる:

hello 
world 
There were 2 tokens found. 

しかし、私はあなたがそのようなことに対処したい疑う:『こんにちは』、 『世界』、その場合、一つの解決策は以下のとおりです。昏睡と

  1. スプリットのみ
  2. その後、(おそらくブースト/アルゴリズム/文字列/ trim.hppまたは正規表現ライブラリを使用して)「」を削除します。

EDIT:追加したプログラムの出力

+0

出力を表示すると、指定した例が改善されます。このページにコードが何をするのかを知る人には、それを豊富に明確にするだけです。 –

2

この明示的なループなしのジェイミー・クックの答えと同じ結果を達成します。

tokenizer<escaped_list_separator<char> >tok(str); 
vector<string> tokens(tok.begin(), tok.end()); 

escaped_list_separator<char>("\\", ",", "\"")にトークナイザのコンストラクタの第二引数のデフォルト値は、それは必要はありません。コンマや引用符の要件が異なる場合を除きます。

関連する問題