C++ 文字列型で後方一致の検索【std::string endsWith/hasSuffix 接尾辞判定】

std::string文字列の後方一致の判定にはends_withメンバ関数を利用することができます(C++20以降)。

std::string{"abc"}.ends_with("bc") // true

C++17以前の文字列クラスstd::stringには、接尾辞(サフィックス)を検索するためのメソッドとしてends_withendsWithhasSuffixが定義されていません。指定の文字列が特定の文字列で終わるかどうかを判定したい場合には、findメンバ関数、compareメンバ関数、std::equal関数による代用が必要となります。

目次

前方一致については、別記事の「前方一致の判定」が参考になります。

ends_withメンバ関数による後方一致の判定

C++20以降のコンパイラであれば、ends_withメンバ関数による前方一致の判定が可能となっています。

std::string s = "abc"; // 検索先の文字列
std::string t = "bc";  // 検索文字列
if (s.ends_with(t)) {
   puts("文字列`bc`で終わる文字列です");
}

引数にはstd::string(厳密にはstd::string_view)型の文字列の他に、C言語スタイルの文字列(const char *)や文字型(char)を利用することができます。

std::string{abc}.ends_with("bc"); // true
std::string{abc}.ends_with('c');  // true

後方一致(suffix search, ends with match)

末尾文字列の一致を判定する方法については、find関数とその検索開始位置の指定を用いてこれを実現します。

std::string s = "abc"; // 検索先の文字列
std::string t = "bc";  // 検索したい文字列

if (s.size() >= t.size() &&
    s.find(t, s.size() - t.size()) != std::string::npos) {
   puts("文字列`bc`で終わる文字列です");
}

他にも、compareメンバ関数を用いる方法があります。

std::string s = "abc";
std::string t = "bc";
if (s.size() >= t.size() &&
    s.compare(s.size() - t.size(), t.size(), t) == 0) {
   puts("文字列`bc`で終わる文字列です");
}

rfind関数の利用法も知られていますが、全文に対する検索が行われるため処理効率はよくありません。仮に利用する場合にはnposによる事前の比較が必須となります。rfindの結果をそのまま判定に利用してしまうと、オフセットによる誤差が発生し、正常な判定が行えなくなります。

/* 非推奨 */
std::string s = "abc";
std::string t = "bc";
std::string::size_type pos = s.rfind(t); // 不一致時に全文検索が発生
if (pos != std::string::npos &&
    s.rfind(t) + t.size() == s.size()) {
   puts("文字列`bc`で終わる文字列です");
}

/* 危険 */
std::string s = "abc";
std::string t = "abcd";
bool found = s.rfind(t) == s.size() - t.size();
found; // true (`s.size() - t.size()`はnposと同じ値になってしまう)

end_with関数

より処理効率の高いend_with関数の定義例は以下の通りです。指定の文字列がsuffixに指定された文字列で終わるかどうかを判定することができます。

// #include <algorithm> // std::equal
// #include <iterator>  // std::rbegin, std::rend
// end_with("abc", "bc") == true
bool end_with(const std::string& s, const std::string& suffix) {
   if (s.size() < suffix.size()) return false;
   return std::equal(std::rbegin(suffix), std::rend(suffix), std::rbegin(s));
}
広告