C++ 文字列の比較を行う方法【equal, compare, ==比較演算子|std::string】

C++の文字列型で等値の判定を行う場合には一般的な比較演算子を用いる方法以外にも、compareメンバ関数やequal関数を用いた様々な方法が存在します。

std::string s = "abc";
s == "abc";                 // 演算子による比較
s == std::string("abc");
s.compare("abc") == 0;      // 演算子による比較と同等の処理
s.compare(1, 2, "bc") == 0; // 検索範囲の指定
s[0]     == 'a';            // 添字演算子による要素比較
s.at(1)  == 'b';            // 要素へのアクセス(範囲外の場合例外発生: std::out_of_range)
s.back() == 'c';            // 末尾要素の取得
std::equal(s.begin(), s.end(), "abc") == true;
                            // イテレータによる比較

目次

比較演算子( == / != )

std::string型の文字列は比較演算子(==, !=)による文字列比較が可能となっています。

std::string s = "ab";
s == "ab"; // true (等値判定)
s != "AB"; // true (不等値判定)

==は文字列全体の一致を判定します。!=は不一致を判定します。C言語スタイル文字列(const char*)との比較も可能です。

s == std::string("ab"); // 同一型同士の比較が可能
s == (const char*)"ab"; // C言語スタイル文字列との比較が可能

"ab" == s;                // ヨーダ記法による左辺比較が可能
std::operator==(s, "ab"); // 非メンバ関数による明示的な演算子関数呼び出し

// error: no member named 'operator==' in 'std::__1::basic_string<char>'
s.operator==("ab");       // メンバ関数としての利用はできない

compare メンバ関数

compareメンバ関数は大小関係を考慮した比較関数です。戻り値型はint型の値です。一致した場合には0が返されます。不一致が発生した場合には正の値または負の値が返されます。

std::string s = "abc";
s.compare("abc"); // 0 (一致)
s.compare("aba"); // 2 (不一致)

using namespace std;

string("b").compare("a"); //  1 (文字型による演算`'b' - 'a'`の結果に相当)
string("b").compare("c"); // -1
string("b").compare("d"); // -2
string("0").compare("9");  // -9 (文字型による演算`'0' - '9'`の結果に相当)
string("10").compare("9"); // -8 (あくまで不一致時の要素を対象とする)

/* 不一致が見つからない場合は文字列長の違いに応じて正の値または負の値を返す */
string("aa").compare("a");   //  1 (自身のほうが大きい場合は正の数)
string("aa").compare("aaa"); // -1 (自身のほうが小さい場合は負の数)

/* 活用例 */
string("b").compare("a") > 0;  // true (比較対象よりも大きな表現かどうか)
string("b").compare("c") < 0;  // true (比較対象よりも小さな表現かどうか)
string("b").compare("b") == 0; // true (等しいかどうか)

compareは検索範囲の指定が可能です。第一引数に検索開始位置、第二引数に検索する長さを指定することができます。

std::string s = "a-b-c";
s.compare(1, 3, "-b-"); // 0
s.compare(3, 2, "-c");  // 0

s.compare(0, 2, "a-b");    // -1
s.compare(0, 2, "a-b", 2); //  0
s.compare(0, 2, std::string("-a-"), 1, 2); // 0

第四引数には第三引数に指定したC言語スタイル文字列の長さを指定することが可能です。第三引数に指定された文字列がstd::string型の場合には第四引数以降に開始位置と長さを指定します。

部分文字列に対するより単純な比較を行いたい場合には# std::equal 関数の利用がオススメです。

operator[]/at/front/back メンバ関数

文字要素による比較を行いたい場合には添字演算子(operator[])やat, front, backメンバ関数を用いて各要素を取得します。

std::string s = "abcd"; /* 以下の比較処理は全てtrueとなる */
'a' == s.front(); // 先頭の要素を取得
'b' == s[1];      // 指定された位置の要素を取得
'c' == s.at(2);   // 指定された位置の要素を取得(例外発生あり)
'd' == s.back();  // 末尾の要素を取得
メンバ関数仕様
operator[](pos)`pos == size()`の場合空文字(`CharT()`)を返す。`pos > size()`時未定義動作
at(pos)`pos >= size()`の場合std::out_of_range例外発生
front`operator[](0)`相当。`empty() == true`時未定義動作
back`operator[](size() - 1)`相当。`empty() == true`時未定義動作

std::equal 関数

algorithmヘッダーのアルゴリズム関数std::equalを用いることで、イテレータを用いた柔軟な検索が実現できます。

// #include <algorithm> /* std::equal */
std::string s = "abc";
std::string t = "abcdefg";
std::equal(s.begin(), s.end(), t.begin()); // true
std::equal(t.begin(), t.end(), s.begin()); // false
std::equal(s.begin(), s.end(), t.begin(), t.begin() + 3); // true

第一引数と第二引数には検索対象とする文字列の範囲を指定します。第三引数には検索したい文字列の開始位置を指定します。オプションとして第四引数に検索したい文字列の検索終了位置を指定することもできます。

文字列の一部を比較することも可能です。

std::string s = "abc";
std::equal(s.begin() + 1, s.end(), "bc"); // true

std::equal関数は様々なコンテナやデータ構造との比較が行えます。

std::string s = "abc";

/* コンテナクラスとの比較 */
std::vector<char> v = {'a', 'b', 'c'};
std::equal(s.begin(), s.end(), v.begin()); // true
std::equal(v.begin(), v.end(), s.begin()); // true
 
/* C言語スタイル文字列との比較 */
const char *c = "abc";
std::equal(s.begin(), s.end(), c);       // true
std::equal(s.begin(), s.end(), "abc");   // true
std::equal(c, c + strlen(c), s.begin()); // true
 
/* 配列との比較 */
char a[] = {'a', 'b', 'c', '\0'};
std::equal(s.begin(), s.end(), a);     // true
std::equal(a, std::end(a), s.begin()); // true

std::equal関数利用時の注意点

NULL終端されていないデータ構造との比較を行う場合には、必ずequal関数の第四引数に終端位置を指定する必要があります。以下の第四引数を省略した例では、equal関数の内部でv[2]相当の不定な要素アクセスが発生してしまいます。v[2]の結果が文字'c'だった場合にはequal関数の結果は真となってしまいます。

std::string s = "abc";
std::vector<char> v = {'a', 'b'}; // または `char a[] = {'a', 'b'};`
equal(begin(s), end(s), begin(v));         // true/false (不定)
equal(begin(s), end(s), begin(v), end(v)); // false (常に安定)

各関数の処理効率について

compareメンバ関数は要素同士の比較に<演算子による比較演算を行います。std::equal関数の場合は==演算子による要素同士の比較が行われます。より高速な比較処理が求められる環境では、std::equal関数の利用を検討してみると良いでしょう。

ちなみにstd::string型の==メンバ演算子による比較は、compareメンバ関数による比較と同等の内部処理が行われます。LLVM/Clangではstd::string("a") == "b"の内部処理はstd::string("a").compare("b") == 0のエイリアスとして定義されています。std::string("a") == std::string("b")std::char_traits<CharT>::compare関数を活用します。

広告