potisanのプログラミングメモ

趣味のプログラマーがプログラミング関係で気になったことや調べたことをいつでも忘れられるようにメモするブログです。はてなブログ無料版なので記事の上の方はたぶん広告です。記事中にも広告挿入されるみたいです。

C++11 STLで文字列から特定の文字を除去する

はじめに

文字列から文字を除去するには様々な方法がありますが,ここではC++11で導入されたラムダ式STLのremove_if,remove_copy_ifを組み合わせて文字を削除する方法を書き残しておきます.なお,MBCSとかだと扱えなくなるので別の処理が必要だと思います.

C++11やラムダ式を使わない場合はoperator()を実装する構造体を定義すれば同じことをできます.

remove_ifとremove_copy_if

remove_ifはイテレーターを引数として元のオブジェクトを破壊的に変更します.Rubyで言えばfunction!に該当する関数です.対してremove_copy_ifは元のオブジェクトを破壊せず別のオブジェクトに書き込みを行います.両者の違いはメモリ使用量及び処理速度かと思います.今回は速度についての検証は行いません(既にどこかで行われていると思います).

ソースコード

#include <string>    // string
#include <algorithm> // remove_if, remove_copy_if
#include <iostream>  // cout, endl

using namespace std;

int main()
{
    // 文字列から破壊的に空白を除去する
    string s1("abc def ghi");
    cout << "元の文字列:"<< s1 << endl;
    auto it = remove_if(s1.begin(), s1.end(),
        [](const char& c){ return isspace(c); });
    cout << "remove_if後の元の文字列:" << s1 << endl;
    cout << "remove_if後に整形した文字列:" << string(s1.cbegin(), it) << endl;
    cout << endl;

    // 文字列から非破壊的に空白を除去する
    string s2("abc def ghi");
    cout << "元の文字列:" << s2 << endl;
    string s3(s2.length(), 0); // メモリは確保する必要がある
    auto it2 = remove_copy_if(s2.begin(), s2.end(), s3.begin(),
        [](const char& c){ return isspace(c); });
    cout << "remove_copy_if後の元の文字列:" << s2 << endl;
    cout << "remove_copy_if後に整形した文字列:" << string(s3.cbegin(), it2) << endl;

    return 0;
}

出力例

元の文字列:abc def ghi
remove_if後の元の文字列:abcdefghihi
remove_if後に整形した文字列:abcdefghi

元の文字列:abc def ghi
remove_copy_if後の元の文字列:abc def ghi
remove_copy_if後に整形した文字列:abcdefghi

備考

ラムダ式[](const char& c){ return isspace(c); }の内部を変更することで任意の文字を削除することができます.例えば,'a'だけを削除するのであれば[](const char& c){ return c == 'a'; }とします.

boostを使えば文字列単位の置換も簡単に行えるのですね.boostjpのboost::algorithm::replace_allに関する部分を参照です.