std::stringをSTLアルゴリズムで使う
C++である文字列からその一部分を抜き出したいとき、std::stringのメンバ関数を見ると、何文字目、何文字分といった数値指定をするAPIが多く、C言語的です。(例:findは見つかった文字が何バイト目にあるかを数値で返却)
そこで、STLアルゴリズムが使えると便利ではないかと思い調べてみました。
using std::string; // 処理対象文字列textの設定 string text = "January, Feburary, (March), Aplil"; // 文字列textから、開き括弧の位置を探しその位置をiteratorで取得 string::iterator openbracket = std::find(text.begin(), text.end(), '('); if (openbracket == text.end()) { std::cerr << "open bracket not found" << std::endl; retrun; } // 文字列textから、閉じ括弧の位置を探しその位置をiteratorで取得 string::iterator closebracket = std::find(openbracket, text.end(), ')'); if (closebracket == text.end()) { std::cerr << "close bracket not found" << std::endl; return; }
と文字列中から開き括弧、閉じ括弧を検索してそれぞれの反復子を取得します。
次に、2つの反復子で指定された範囲を別な文字列として抜粋します。
- 最初は、std::string自体に用意された手段です。
// イテレータで指定した範囲から新たな文字列を生成 string subset1(openbracket+1, closebracket); // イテレータで指定した範囲を文字列に適用 string subset2; subset2.assign(openbracket+1, closebracket);
string subset;
std::copy(openbracket+1, closebracket, subset.begin());
copyアルゴリズムで、イテレータ範囲を文字列subsetの頭から入れたかったのですが、コピーされず、subsetは空文字列のままです。
-
- 成功例
- insert_iteratorを使う(1)
- 成功例
string subset;
std::insert_iterator<string> insit(subset, subset.begin());
std::copy(openbracket+1, closebracket, insit);
-
-
- insert_iteratorを使う(2)
-
string subset;
std::copy(openbracket+1, closebracket, std::inserter(subtext, subtext.begin());
insert_iteratorを返す関数std::inserterを使用したものです。
-
-
- コピーする文字列数に合わせて文字列のサイズを確保しておく
-
string subset(closebracket - openbracket - 1, '#'); std::copy(openbracket+1, closebracket, subset.begin());
stringにはサイズだけ指定したコンストラクタがないので、サイズとダミーの文字を指定しておきます。
数値の-1,+1が非常に間違いやすい(バグの原因)です。(現に最初間違えてました)
2009/1/18修正
eldeshさんコメントを受けて、サンプルコードを修正しました。