「boost::split」の版間の差分
提供: C++入門
(ページの作成:「<!-- vim: filetype=mediawiki --> C++で文字列を分割する場合には、 boost::split を利用すると簡単にできます。 読み方 ぶーすと すぷ...」) |
(→ソースコード) |
||
(同じ利用者による、間の10版が非表示) | |||
行3: | 行3: | ||
--> | --> | ||
− | C++で文字列を分割する場合には、 boost::split を利用すると簡単にできます。 | + | C++で文字列を分割する場合には、 [[boost::split]] を利用すると簡単にできます。 |
読み方 | 読み方 | ||
行18: | 行18: | ||
どちらも実装しないといけないので、非常に面倒です。 | どちらも実装しないといけないので、非常に面倒です。 | ||
− | もっと簡単にやる方法は、 boost::split を使うことです。 | + | もっと簡単にやる方法は、 [[boost::split]] を使うことです。 |
+ | |||
+ | また、文字列の前後のデミリタの処理には、[[boost::trim]]を利用するとよいでしょう。 | ||
== ヘッダファイル == | == ヘッダファイル == | ||
行28: | 行30: | ||
== ソースコード == | == ソースコード == | ||
− | スペースで区切られた文字列をスペースで分割し、 [[list]] に入れる例です。 | + | スペースで区切られた文字列をスペースで分割し、 [[std::list]] に入れる例です。 |
<syntaxhighlight lang="cpp"> | <syntaxhighlight lang="cpp"> | ||
行111: | 行113: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | == | + | == デミリタを複数指定する == |
+ | 複数のデミリタを指定したいこともあるでしょう。 | ||
+ | |||
+ | デミリタには、複数の文字を指定できます。 | ||
+ | |||
+ | <syntaxhighlight lang="cpp"> | ||
+ | #include <iostream> | ||
+ | |||
+ | #include <boost/foreach.hpp> | ||
+ | using namespace std; | ||
+ | int | ||
+ | main () | ||
+ | { | ||
+ | string str ("127.0.0.1-192.168.0.1*192.168.0.2 192.168.0.3"); | ||
+ | string delim (" *-"); | ||
+ | |||
+ | list<string> list_string; | ||
+ | |||
+ | boost::split(list_string, str, boost::is_any_of(delim)); | ||
+ | |||
+ | BOOST_FOREACH(string s, list_string) { | ||
+ | cout << s << endl; | ||
+ | } | ||
+ | return 0; | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | 実行例 | ||
+ | <syntaxhighlight lang="bash"> | ||
+ | 127.0.0.1 | ||
+ | 192.168.0.1 | ||
+ | 192.168.0.2 | ||
+ | 192.168.0.3 | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | == 空文字列を無視する == | ||
+ | |||
+ | デミリタが複数重なった場合などは、空の文字列が [[list]] に入ってしまいます。 | ||
+ | |||
+ | たとえばこういうときには | ||
+ | <syntaxhighlight lang="cpp"> | ||
+ | string str ("127.0.0.1----- 192.168.0.1**** *192.168.0.2 192.168.0.3"); | ||
+ | string delim (" *-"); | ||
+ | list<string> list_string; | ||
+ | boost::split(list_string, str, boost::is_any_of(delim) ); | ||
+ | </syntaxhighlight> | ||
+ | 下記のようになってしまいます。 | ||
+ | <syntaxhighlight lang="bash"> | ||
+ | % ./a.out | ||
+ | 127.0.0.1 | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | 192.168.0.1 | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | 192.168.0.2 | ||
+ | 192.168.0.3 | ||
+ | % | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | 空文字列は、不要なこともあるでしょう。 | ||
+ | |||
+ | boost::split の第3引数にパラメータをセットすることで、空文字列を無視できます。 | ||
+ | |||
+ | <syntaxhighlight lang="cpp"> | ||
+ | #include <boost/algorithm/string.hpp> | ||
+ | #include <string> | ||
+ | #include <list> | ||
+ | #include <iostream> | ||
+ | #include <boost/foreach.hpp> | ||
+ | using namespace std; | ||
+ | int | ||
+ | main () | ||
+ | { | ||
+ | string str ("127.0.0.1----- 192.168.0.1**** *192.168.0.2 192.168.0.3"); | ||
+ | string delim (" *-"); | ||
+ | |||
+ | list<string> list_string; | ||
+ | |||
+ | boost::split(list_string, str, boost::is_any_of(delim), boost::algorithm::token_compress_on ); | ||
+ | |||
+ | BOOST_FOREACH(string s, list_string) { | ||
+ | cout << s << endl; | ||
+ | } | ||
+ | return 0; | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | 実行例 | ||
+ | <syntaxhighlight lang="bash"> | ||
+ | % ./a.out | ||
+ | 127.0.0.1 | ||
+ | 192.168.0.1 | ||
+ | 192.168.0.2 | ||
+ | 192.168.0.3 | ||
+ | % | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | == 先頭や末尾のデミリタは取り除くしかない == | ||
+ | |||
+ | 下記の場合、最初と最後に空白が入ってしまいます。 | ||
+ | <syntaxhighlight lang="cpp"> | ||
+ | string str (" 127.0.0.1----- 192.168.0.1**** *192.168.0.2 192.168.0.3 "); | ||
+ | string delim (" *-"); | ||
+ | list<string> list_string; | ||
+ | boost::split(list_string, str, boost::is_any_of(delim), | ||
+ | boost::algorithm::token_compress_on ); | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | 行頭、行末は、 trim_if / trim でスペースを取り除くしか無いようです。 | ||
+ | もしくは、 [[boost::tokenizer]] のほうが簡単にできるかもしれません。 | ||
+ | |||
+ | 詳しくは、[[boost::trim]] をご参照ください。 | ||
+ | |||
+ | == 関連項目 == | ||
+ | * [[boost::tokenizer]] | ||
+ | * [[boost::trim]] | ||
* [[Boost]] | * [[Boost]] | ||
* [[C++ライブラリ]] | * [[C++ライブラリ]] | ||
+ | * [[std::split]] | ||
+ | * [[std::string]] |
2014年1月3日 (金) 19:24時点における最新版
C++で文字列を分割する場合には、 boost::split を利用すると簡単にできます。
読み方
ぶーすと すぷりっと
概要
C言語の場合、文字列を分解するときに、strtok を使ったりします。 C++の場合は、string の find_first_of を使って、ループを回していくやりかたもあります。
どちらも実装しないといけないので、非常に面倒です。
もっと簡単にやる方法は、 boost::split を使うことです。
また、文字列の前後のデミリタの処理には、boost::trimを利用するとよいでしょう。
ヘッダファイル
#include <boost/algorithm/string.hpp> // boost:spplit
ソースコード
スペースで区切られた文字列をスペースで分割し、 std::list に入れる例です。
#include <boost/algorithm/string.hpp> #include <string> #include <list> #include <iostream> #include <boost/foreach.hpp> using namespace std; int main () { string str ("192.168.0.1 192.168.0.2"); list<string> list_string; boost::split(list_string, str, boost::is_space()); BOOST_FOREACH(string s, list_string) { cout << s << endl; } return 0; }
文字列を分割する文字(デミリタ)がカンマの場合は、以下のようになります。
#include <boost/algorithm/string.hpp> #include <string> #include <list> #include <iostream> #include <boost/foreach.hpp> using namespace std; int main () { string str ("192.168.0.1,192.168.0.2"); string delim (","); list<string> list_string; boost::split(list_string, str, boost::is_any_of(delim)); BOOST_FOREACH(string s, list_string) { cout << s << endl; } return 0; }
複数のデリミタを指定できます。
#include <boost/algorithm/string.hpp> #include <string> #include <list> #include <iostream> #include <boost/foreach.hpp> using namespace std; int main () { string str ("127.0.0.1-192.168.0.1*192.168.0.2 192.168.0.3"); string delim (" *-"); list<string> list_string; boost::split(list_string, str, boost::is_any_of(delim)); BOOST_FOREACH(string s, list_string) { cout << s << endl; } return 0; }
コンパイル
clang++ -I/usr/local/include boost_split.cpp
デミリタを複数指定する
複数のデミリタを指定したいこともあるでしょう。
デミリタには、複数の文字を指定できます。
#include <iostream> #include <boost/foreach.hpp> using namespace std; int main () { string str ("127.0.0.1-192.168.0.1*192.168.0.2 192.168.0.3"); string delim (" *-"); list<string> list_string; boost::split(list_string, str, boost::is_any_of(delim)); BOOST_FOREACH(string s, list_string) { cout << s << endl; } return 0; }
実行例
127.0.0.1 192.168.0.1 192.168.0.2 192.168.0.3
空文字列を無視する
デミリタが複数重なった場合などは、空の文字列が list に入ってしまいます。
たとえばこういうときには
string str ("127.0.0.1----- 192.168.0.1**** *192.168.0.2 192.168.0.3"); string delim (" *-"); list<string> list_string; boost::split(list_string, str, boost::is_any_of(delim) );
下記のようになってしまいます。
% ./a.out 127.0.0.1 192.168.0.1 192.168.0.2 192.168.0.3 %
空文字列は、不要なこともあるでしょう。
boost::split の第3引数にパラメータをセットすることで、空文字列を無視できます。
#include <boost/algorithm/string.hpp> #include <string> #include <list> #include <iostream> #include <boost/foreach.hpp> using namespace std; int main () { string str ("127.0.0.1----- 192.168.0.1**** *192.168.0.2 192.168.0.3"); string delim (" *-"); list<string> list_string; boost::split(list_string, str, boost::is_any_of(delim), boost::algorithm::token_compress_on ); BOOST_FOREACH(string s, list_string) { cout << s << endl; } return 0; }
実行例
% ./a.out 127.0.0.1 192.168.0.1 192.168.0.2 192.168.0.3 %
先頭や末尾のデミリタは取り除くしかない
下記の場合、最初と最後に空白が入ってしまいます。
string str (" 127.0.0.1----- 192.168.0.1**** *192.168.0.2 192.168.0.3 "); string delim (" *-"); list<string> list_string; boost::split(list_string, str, boost::is_any_of(delim), boost::algorithm::token_compress_on );
行頭、行末は、 trim_if / trim でスペースを取り除くしか無いようです。 もしくは、 boost::tokenizer のほうが簡単にできるかもしれません。
詳しくは、boost::trim をご参照ください。