さよなら煩わしい検索!C++のstd::basic_string_view::containsでスマートに文字列を見つけよう


メソッドの動作

このメソッドは、以下の引数を取ります。

  • pos: 検索を開始する位置 (デフォルトは 0)
  • sub: 検索対象となる部分文字列ビュー

メソッドは、subthis1 回以上出現するかどうか を調べ、true または false を返します。

#include <iostream>
#include <string_view>

int main() {
  std::string_view haystack = "Hello, world!";
  std::string_view needle = "world";

  // "world" が "Hello, world!" に含まれているかどうかを確認
  if (haystack.contains(needle)) {
    std::cout << "needle が haystack に含まれています" << std::endl;
  } else {
    std::cout << "needle が haystack に含まれていません" << std::endl;
  }

  // 検索開始位置を指定
  if (haystack.contains(needle, 7)) {
    std::cout << "needle が haystack の 7 文字目以降に含まれています" << std::endl;
  } else {
    std::cout << "needle が haystack の 7 文字目以降に含まれていません" << std::endl;
  }

  return 0;
}

この例では、haystackneedle が含まれているかどうかを 2 回チェックしています。1 回目はデフォルトの開始位置 (0) で、2 回目は pos を 7 に設定して検索を開始しています。

  • std::basic_string_view::contains は、C++20 で導入された比較的新しい機能です。古いバージョンの C++ コンパイラを使用している場合は、この機能を使用できない可能性があります。
  • std::basic_string_view::contains は、効率的な検索アルゴリズム を使用しています。そのため、長い文字列を検索する場合でも、比較的短い時間で処理することができます。
  • std::basic_string_view::contains は、部分文字列マッチ のみを行います。つまり、needlehaystack の先頭に一致するかどうかのみを調べます。完全一致を確認するには、std::basic_string_view::find メソッドを使用する必要があります。


部分文字列の存在チェック

#include <iostream>
#include <string_view>

int main() {
  std::string_view haystack = "Hello, world!";
  std::string_view needles[] = {
    "Hello",
    "world",
    "Good bye",
  };

  for (std::string_view needle : needles) {
    if (haystack.contains(needle)) {
      std::cout << needle << " は haystack に含まれています" << std::endl;
    } else {
      std::cout << needle << " は haystack に含まれていません" << std::endl;
    }
  }

  return 0;
}

このコードは、haystack という文字列ビューに、needles 配列に格納されている複数の部分文字列が含まれているかどうかを調べます。

大文字小文字を無視した検索

#include <iostream>
#include <string_view>
#include <algorithm>

int main() {
  std::string_view haystack = "Hello, World!";
  std::string_view needle = "world";

  // 大文字小文字を無視して検索
  if (std::search(haystack.begin(), haystack.end(), needle.begin(), needle.end(), std::equal_insensitive)) {
    std::cout << needle << " は haystack に含まれています (大文字小文字を無視した場合)" << std::endl;
  } else {
    std::cout << needle << " は haystack に含まれていません (大文字小文字を無視した場合)" << std::endl;
  }

  return 0;
}

このコードは、std::search アルゴリズムと std::equal_insensitive 関数を使って、haystackneedle大文字小文字を無視して 含まれているかどうかを調べます。

#include <iostream>
#include <string_view>
#include <sstream>

int main() {
  std::string_view haystack = "This is a string with multiple words.";
  std::string_view delimiter = " ";
  std::string_view needle = "words";

  std::istringstream iss(haystack);
  std::string_view token;

  while (std::getline(iss, token, delimiter)) {
    if (token.contains(needle)) {
      std::cout << needle << " は " << token << " に含まれています" << std::endl;
    }
  }

  return 0;
}


以下に、std::basic_string_view::contains の代替となるいくつかの方法をご紹介します。

std::find を使用する

std::find アルゴリズムは、ある範囲内に特定の値が含まれているかどうかを調べることができます。以下のコードは、std::basic_string_view::contains と同等の機能を提供します。

bool contains(std::string_view haystack, std::string_view needle) {
  return std::find(haystack.begin(), haystack.end(), needle.begin(), needle.end()) != haystack.end();
}

カスタム関数を使用する

独自の検索ロジックを実装したい場合は、カスタム関数を作成することができます。以下のコードは、std::basic_string_view::contains と同等の機能を提供する単純な例です。

bool contains(std::string_view haystack, std::string_view needle) {
  for (size_t i = 0; i < haystack.size() - needle.size() + 1; ++i) {
    if (haystack.substr(i, needle.size()) == needle) {
      return true;
    }
  }
  return false;
}

正規表現を使用する

正規表現を使用すれば、より複雑な検索パターンを記述することができます。以下のコードは、std::basic_string_view::contains と同等の機能を提供する std::regex を使用した例です。

#include <regex>

bool contains(std::string_view haystack, std::string_view needle) {
  std::regex re(needle);
  return std::regex_search(haystack, re);
}

Boost.StringView ライブラリを使用する

Boost.StringView ライブラリは、C++ 標準ライブラリの std::string_view クラスを拡張するものです。このライブラリには、contains メソッドを含むいくつかの便利な機能が含まれています。

#include <boost/sview/string_view.hpp>

bool contains(boost::sview::string_view haystack, boost::sview::string_view needle) {
  return haystack.contains(needle);
}

どの代替方法を使用すべきか

どの代替方法を使用するかは、状況によって異なります。

  • Boost.StringView ライブラリを使用している場合は、このライブラリの contains メソッドを使用することができます。
  • 複雑な検索パターンを記述する必要がある場合は、正規表現を使用するのが良いでしょう。
  • カスタムの検索ロジックが必要な場合は、カスタム関数を作成する必要があります。
  • シンプルで分かりやすい方法が必要な場合は、std::find を使用するのが良いでしょう。
  • 保守性: 将来的に変更が必要になった場合に、コードを簡単に更新できるようにする必要があります。
  • 可読性: コードは、他の開発者にとって読みやすく理解しやすいように記述する必要があります。
  • パフォーマンス: それぞれの方法のパフォーマンスは異なります。ベンチマークを実施して、最適な方法を選択することが重要です。