「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 をご参照ください。

関連項目