C++ 文字列型で前方一致の検索【std::string startsWith/hasPrefix 接頭辞判定】

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

std::string{"abc"}.starts_with("ab") // true

ただしC++20より前の古いコンパイラの場合、C++の文字列クラスstd::stringには接頭辞(プレフィックス)を検索するためのメソッドとしてstarts_withstartsWithhasPrefix等の関数が定義されていません。

そのため、指定の文字列が特定の文字列で始まるかどうかを判定したい場合には、std::equal関数やfindメンバ関数、compareメンバ関数による代用が必要となります。

目次

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

前方一致(prefix search, starts with)

starts_withメンバ関数による判定

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

std::string s = "abc"; // 検索先の文字列
std::string t = "ab";  // 検索文字列
if (s.starts_with(t)) {
   puts("文字列`ab`で始まる文字列です");
}

starts_withはstd::string_view型の引数を受け取るメンバ関数として定義されています。そのためstd::string型の値を渡すことも可能となっています。また引数には多重定義により、C言語スタイルの文字列(const char *)や文字型(char)を利用することもできます。

std::string{abc}.starts_with("ab"); // true
std::string{abc}.starts_with('a');  // true

std::equal関数による判定

std::string型文字列に対して、先頭文字列の一致を判定するためには、std::equal関数による比較がもっとも効率的です。

// #include <algorithm> // std::equal

std::string s = "abc"; // 検索先の文字列
std::string t = "ab";  // 検索文字列
if (s.size() >= t.size() &&
    std::equal(std::begin(t), std::end(t), std::begin(s))) {
   puts("文字列`ab`で始まる文字列です");
}

C言語スタイルの文字列による検索を行う場合には、若干の改変が必要となります。

std::string s = "abc";
const char* t = "ab"; // 検索文字列(文字列ポインタ)
size_t n = std::char_traits<char>::length(t); // 検索文字列の長さ
if (s.size() >= n && std::equal(t, t + n, std::begin(s))) {
   puts("文字列`ab`で始まる文字列です");
}
参考: std::equal関数

findメンバ関数による判定

先頭文字列の一致を判定するためには、findメンバ関数の利用がもっとも手っ取り早い方法ですが、長文検索時の処理効率はあまり良くありません。

std::string s = "abc";

if (s.find("ab") == 0) {
   puts("文字列`ab`で始まる文字列です");
}

// char型の文字を検索することも可能
if (s.find('a') == 0) puts("文字`a`で始まる文字列です");

findメンバ関数は一致する文字列が見つかるまで全文を検索するため、先頭文字列が一致しなかった場合でも、文字列の末尾まで余計な検索が行われてしまうことになります。

参考: findメンバ関数

compareメンバ関数による判定

findメンバ関数は全文検索が発生する場合があるため、より効率的な処理を求める場合には、検索開始位置と終了位置の指定が可能なcompareメンバ関数への置き換えが有効です。

std::string s = "abc";
std::string t = "ab";

if (s.size() >= t.size() &&
    s.compare(0, t.size(), t) == 0) {
   puts("文字列`ab`で始まる文字列です");
}

ただし、compareメンバ関数は検索文字列の大小比較を伴うため、より処理効率の高いプログラムを求める場合には、冒頭で説明した「# std::equal関数による判定」による比較テクニックの利用が必要となります。

参考: compare メンバ関数

文字/文字集合による判定

char型の文字を検索する場合は添字アクセスの利用がより効率的な処理となります。

std::string s = "abc";
if (s[0] == 'a') puts("文字`a`で始まる文字列です");

find_first_ofメンバ関数を用いることで、複数の文字のいずれかの文字で始まるかどうかを判定することもできます。

std::string s = "abc";
if (s.find_first_of("Aa") == 0) {
   puts("文字`A`または`a`で始まる文字列です");
}

start_with関数

以下はequal関数を用いたstart_with関数の実装例です。指定の文字列sprefixに指定された文字列で始まるかどうかを判定することができます。

bool start_with(const std::string& s, const std::string& prefix) {
   if (s.size() < prefix.size()) return false;
   return std::equal(std::begin(prefix), std::end(prefix), std::begin(s));
}
assert(  start_with("abc", "")     );
assert(  start_with("abc", "a")    );
assert(  start_with("abc", "ab")   );
assert(  start_with("abc", "abc")  );
assert( !start_with("abc", "abcd") );
広告