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;
// イテレータによる比較
目次
- 比較演算子( == / != )
- compare メンバ関数(検索範囲の指定が可能)
- operator[]/at/front/back メンバ関数(要素を比較したい場合)
- std::equal 関数(イテレータを用いた柔軟な比較が可能)
- 各関数の処理効率について
比較演算子( == / != )
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
関数を活用します。