👀

std::stringで特定の文字列から開始しているか?をチェックする

2025/02/22に公開

最近C言語の文字列を使っているコードをstd::stringを使う C++ のコードに変えるリファクタリングを結構しています。

もちろんどちらを使ってもいいと思いますし、どちらにもメリットとデメリットがありますが、比較に関しては圧倒的にstd::stringの方が優れていると思います。
今回は一番使われる比較のパターンをいくつかを比べてみましょう。

以下のような変数があるとしましょう。

char cWord1[20] = "test1";
char cWord2[20] = "test2";
std::string cppWord1("test1");
std::string cppWord2("test2");

文字列が完全一致かのチェック

if (strcmp(cWord1, cWord2) == 0) {}
if (cppWord1 == cppWord2) {}

単純な等価比較はどちらも割とシンプルですが、C++ の方が関数をコールしなくていいので一番シンプルですね。後、strcmpは文字列が同じ場合はtrueに当たる1ではなく、falseに当たる0を返すので、そのままif文の条件として使えなくて、0と比較しないといけないのが個人的に使いづらいです。

特定の文字列で始まっているかのチェック

if (strncmp(cWord1, cWord2, sizeof(cWord2)) == 0) {}
if (cppWord1.find(cppWord2) == 0) {}

ここはどちらもやり方が色々あると思いますが、個人的に一番使いやすくて短いやり方を比較してみました。strncmpはかなり万能で、割とどの比較でも使えますが、比較する文字数を渡さないといけないのがこのケースだとちょっと使いづらいですね。ここも C++ の専用の関数の方が使いやすいと思います。

たまにstrncmpで2つの文字列が完全一致しているかをチェックしているコードを見かけるのですが、文字列がどちらもNULL終端されていない場合はstrcmpはクラッシュするまで比較し続けるというエッジケースもあるため、strncmpの方が無難という認識が強いからかもしれないです。でもstrncmpを使い際に気を付けないといけないことがあります。例えば、上記の場合は、cWord2の文字数分しか比較していないため、cWord1が「test12345」でcWord2が「test」の場合も、strncmpは成功してしまいます。なので、strncmpで完全一致したい場合は、その前に文字数が一致しているかをチェックしないといけないです。

if (sizeof(cWord1) == sizeof(cWord2) && strncmp(cWord1, cWord2, sizeof(cWord2)) == 0) {}

特定の文字列で終わっているかのチェック

if (strncmp(cWord1 + (sizeof(cWord1) - sizeof(cWord2)), cWord2, sizeof(cWord2)) == 0) {}
if (cppWord1.compare(cppWord1.length() - cppWord2.length(), cppWord2.length(), cppWord2) == 0) {}

ここはどちらもあんまり変わらないですね。正直どちらも使いづらいです。

特定の文字列で始まっているかのチェックと特定の文字列で終わっているかのチェックに関しては、C++20 で専用の関数が追加されました。

if (cppWord1.starts_with(cppWord2)) {}
if (cppWord1.ends_with(cppWord2)) {}

なんでこういう便利な関数がもっと早く追加されなかったのだろうという質問は残りますが、ぜひ使ってみてください。


|cpp記事一覧へのリンク|

Discussion