STLのalgorithmの練習1
STLのalgorithmを使うと、vectorやlistなどのコンテナに対してソートや置き換え、検索などを簡単に行うことができます。
algorithmが提供している関数ごとに違いはありますが、大まかな書式は次のようになります。
std::<関数名>(<前iteretor>,<後ろiteretor>,<値・配列>,<値・配列2>,<条件・比較用関数>)
初めの2つの引数は、処理を行う対象範囲の始めと終わりを指すイテレータです。そのあとに、必要な個数だけキーとなる値や配列などを指定して、最後に条件・比較のための関数やクラスを指定します。
例えば、vectorに文字列が入っているとして、対象となる文字が母音のときのみoをeに変換する処理を行うには下のような書式で記述できます。IsVowelは母音かどうかを判定する関数です。
std::vector<char> v;//値が既に入っている std::replace_if(v.begin(), v.end(), 'o', 'e' , IsVowel);
偶数のみ検索する関数は下のように書くことができます。IsEvenは偶数かどうかを判定する関数です。
std::find_if (v.begin(), v.end(), IsEven);
条件を付けない場合はIsEvenを省略できます。
std::find_if (v.begin(), v.end());
関数ごとに仕様は全て異なるので、正確にはひとつずつ調べなければなりませんが、使い方はどの関数も似ています。
最後の引数を指定するには、条件付けのための関数を用意してその関数のアドレスを渡す方法と、クラスを用意してインスタンスを渡す方法があります。
関数を利用するパターン
コンテナの要素が整数型で、一つの要素を対象にしている場合は、整数型の引数が1個の関数を定義すれば条件処理を実現することができます。
bool IsEven(int i){ return ( i%2 == 0 ); }
it = std::find_if (v.begin(), v.end(), IsEven);
ソート関数では引数が2個の比較関数を設定します。基本的に細かい仕様は関数ごとに異なりますが、関数ポインタを渡す点はどれも同じです。
bool compare(int i,int j) { return (i<j); }
sort (v.begin(), v.end(), compare);
クラスを利用するパターン
同じ処理をクラスを利用して実現するには、クラス内で()operatorを定義して、クラスのインスタンスを渡します。
class IsEven{ public: bool operator()(int i){ return ( i%2 == 0 ); } };
it = std::find_if (v.begin(), v.end(), IsEven());
STLのalgorithmで用意されている関数は基本的には上で述べたように使うことができます。そこで、algorithmで使える関数の中からいくつかピックアップして、簡単な例を作成してみたいと思います。
まずは、比較、検索、カウントなどコンテナの要素を書き換えない関数の例を見てみます。
find
特定の要素を検索して、見つかった要素を指すイテレータを返します。
判定用の関数と組み合わせて、特定の条件を満たす要素のみ検索することができるfind_ifなどの関数も用意されています。
//判定用関数の定義 bool IsEven(int i){ return ( i%2 == 0 ); }
int iArray[] = {15,40,35,20}; std::vector<int> v (iArray, iArray+4); std::vector<int>::iterator it; it = std::find (v.begin(), v.end(), 35); std::cout << *(++it) << std::endl; //20 it = std::find_if (v.begin(), v.end(), IsEven); std::cout << *it << std::endl; //40
count
特定の要素が何度出現するか数えることができます。また、count_ifを使うと特定の条件を満たす要素だけ数えられます。
下の例ではeが2回、母音が3回出現しています。
bool IsVowel (char c) { return (c == 'a') || \ (c == 'i') || \ (c == 'u') || \ (c == 'e') || \ (c == 'o') ; }
char cArray[] = {'e','l','e','c','t','r','o','n'}; std::vector<char> v (cArray, cArray+7); std::vector<char>::iterator it; int count = std::count (v.begin(), v.end(), 'e'); int count2 = std::count_if (v.begin(), v.end(), IsVowel); std::cout << count << std::endl; //2 std::cout << count2 << std::endl; //3
search
特定の配列や文字列を検索して先頭を指すイテレータを返します。
valという文字列は1番目に見つかります。
char cArray[] = "evaluation"; std::vector<int> v (cArray, cArray+10); std::vector<int>::iterator it; char key[]="val"; it = std::search (v.begin(), v.end(), key, key+3); if (it!=v.end()){ std::cout << int(it-v.begin()) << "番目に見つかりました。" << std::endl; } else{ std::cout << key << "は見つかりませんでした。" << std::endl; }
equal
コンテナと配列を比較して要素が全て同じかどうかを調べることができます。
char cArray[] = "strings"; std::vector<int> v (cArray, cArray+7); std::vector<int>::iterator it; char key[]="strings"; if( std::equal(v.begin(), v.end(), key) == true ){ std::cout << "equal" << std::endl; }
mismatch
異なる要素を検索して、pairとして返します。
char cArray1[] = "simulation"; char key[] = "stimulation"; std::vector<char> v1 (cArray1, cArray1+10); std::vector<char>::iterator it; std::pair< std::vector<char>::iterator, char* > result; result = std::mismatch(v1.begin(), v1.end(), key ); std::cout << *result.first << "," << *result.second << std::endl;