C++の`std::basic_string::ends_with`でできることは?サンプルコードで分かりやすく解説


std::basic_string::ends_with は、C++標準ライブラリに含まれる std::basic_string クラスのメソッドの一つで、文字列が特定のサフィックスで終わっているかどうかを判定します。これは、ファイル形式の識別、データ検証、テキスト処理など、様々な場面で役立つ機能です。

メソッドの構文

bool ends_with(const std::basic_string_view& suffix);
bool ends_with(const char* suffix);
bool ends_with(char suffix);

引数

  • suffix: 検査対象のサフィックスを表す std::basic_string_view オブジェクト、const char* ポインタ、または単一の文字

戻り値

  • 検査対象の文字列がサフィックスで終わっている場合は true、そうでない場合は false

詳細説明

ends_with メソッドは、検査対象の文字列の末尾部分と、引数として渡されたサフィックスを比較します。比較は、文字列の各対応する位置における文字の一致に基づいて行われます。

std::string str = "Hello, World!";

// サフィックスが "World!" であるかどうかを検査
if (str.ends_with("World!")) {
  std::cout << "The string ends with 'World!'" << std::endl;
} else {
  std::cout << "The string does not end with 'World!'" << std::endl;
}

この例では、str 文字列が "World!" で終わっているため、if ステートメントが実行され、"The string ends with 'World!'" というメッセージが出力されます。

サフィックスの種類

ends_with メソッドは、以下の3種類のサフィックスを受け付けます。

  1. std::basic_string_view オブジェクト: サフィックスを表す文字列ビューオブジェクト。これは、std::string オブジェクトや const char* ポインタからの暗黙的な変換を含む、様々な形式の文字列ビューを受け入れる柔軟な方法です。
  2. const char* ポインタ: サフィックスを表すヌル文字で終端された文字列ポインタ。これは、Cスタイルの文字列リテラルを使用する場合に便利です。
  3. 単一の文字: サフィックスを表す単一の文字。これは、文字列が特定の文字で終わっているかどうかを検査する場合に役立ちます。

注意点

  • 効率的なパフォーマンスのために、ends_with メソッドは、検査対象の文字列の末尾部分のみを比較します。
  • サフィックスの比較は、ロケール設定の影響を受けません。つまり、大文字と小文字は区別されません。
  • ends_with メソッドは、サフィックスの長さが検査対象の文字列の長さよりも大きい場合、常に false を返します。

std::basic_string::ends_with メソッドは、C++における文字列操作において非常に有用なツールです。サフィックスの存在確認、データ検証、テキスト処理など、様々な場面で活用できます。メソッドの構文と挙動を理解し、適切な引数を選択することで、効率的かつ正確な文字列処理を実現することができます。

  • 標準ライブラリに含まれる std::algorithm ヘッダーファイルには、std::equalstd::search などの文字列比較アルゴリズムが用意されています。これらのアルゴリズムは、ends_with メソッドよりも柔軟な文字列比較機能を提供します。
  • C++20 では、std::stringstd::string_view クラスに starts_with メソッドが追加されました。これは、文字列が特定のプレフィックスで始まるかどうかを判定するものです。


例 1: サフィックスが文字列の一部であるかどうかを調べる

#include <iostream>
#include <string>

int main() {
  std::string str = "This is an example string";

  // サフィックスが "example" であるかどうかを検査
  if (str.ends_with("example")) {
    std::cout << "The string ends with 'example'" << std::endl;
  } else {
    std::cout << "The string does not end with 'example'" << std::endl;
  }

  // サフィックスが "ing" であるかどうかを検査
  if (str.ends_with("ing")) {
    std::cout << "The string ends with 'ing'" << std::endl;
  } else {
    std::cout << "The string does not end with 'ing'" << std::endl;
  }

  return 0;
}

この例では、str 文字列が "example" と "ing" の両方で終わっているかどうかを検査します。最初の if ステートメントは true を返し、2番目の if ステートメントは true を返します。

例 2: 文字列ビューサフィックスを使用する

#include <iostream>
#include <string>
#include <string_view>

int main() {
  std::string str = "Hello, World!";
  std::string_view suffix = "World!";

  // サフィックスが "World!" であるかどうかを検査
  if (str.ends_with(suffix)) {
    std::cout << "The string ends with 'World!'" << std::endl;
  } else {
    std::cout << "The string does not end with 'World!'" << std::endl;
  }

  return 0;
}

この例では、std::string_view オブジェクトを使用して、ends_with メソッドにサフィックスを渡します。これは、std::string オブジェクトをコピーせずにサフィックスを参照できる便利な方法です。

例 3: 単一の文字サフィックスを使用する

#include <iostream>
#include <string>

int main() {
  std::string str = "Goodbye.";

  // サフィックスが "." であるかどうかを検査
  if (str.ends_with('.')) {
    std::cout << "The string ends with a period ('.')." << std::endl;
  } else {
    std::cout << "The string does not end with a period ('.')." << std::endl;
  }

  return 0;
}

この例では、単一の文字 "." をサフィックスとして使用して、str 文字列がピリオドで終わっているかどうかを検査します。

例 4: ロケール設定の影響

#include <iostream>
#include <string>
#include <locale>

int main() {
  std::string str = "Hello, World!";

  // ロケールを英語 (US) に設定
  std::locale::global(std::locale("en_US.UTF-8"));

  // サフィックスが "WORLD!" であるかどうかを検査 (大文字で比較)
  if (str.ends_with("WORLD!")) {
    std::cout << "The string ends with 'WORLD!'" << std::endl;
  } else {
    std::cout << "The string does not end with 'WORLD!'" << std::endl;
  }

  return 0;
}

この例では、ロケールを英語 (US) に設定し、str 文字列が "WORLD!" で終わっているかどうかを大文字で比較します。ロケール設定が異なると、比較結果が異なる場合があります。

#include <iostream>
#include <string>
#include <algorithm>

int main() {
  std::string str = "This is a test string";
  std::string suffix = "test";

  // サフィックスが "test" であるかどうかを検査 (std::equal を使用する)
  auto it = std::end(str) - suffix


手動比較

最も基本的な方法は、手動で文字列の末尾部分とサフィックスを比較することです。以下のコード例のように、ループを使用して文字列の各文字を比較することができます。

#include <iostream>
#include <string>

bool ends_with(const std::string& str, const std::string& suffix) {
  if (suffix.size() > str.size()) {
    return false;
  }
  for (size_t i = str.size() - suffix.size(); i < str.size(); ++i) {
    if (str[i] != suffix[i - str.size() + suffix.size()]) {
      return false;
    }
  }
  return true;
}

int main() {
  std::string str = "Hello, World!";
  std::string suffix = "World!";

  if (ends_with(str, suffix)) {
    std::cout << "The string ends with '" << suffix << "'" << std::endl;
  } else {
    std::cout << "The string does not end with '" << suffix << "'" << std::endl;
  }

  return 0;
}

長所

  • ヘッダーファイルのインクルードが不要
  • シンプルで理解しやすい

短所

  • エッジケースの処理が必要
  • std::basic_string::ends_with よりも非効率

サフィックス付き部分文字列検索

std::basic_string::find_last_of メソッドを使用して、サフィックスと一致する最後の部分文字列の位置を検索することができます。この方法では、サフィックスが見つかった場合は部分文字列の開始位置が返され、見つからない場合は std::string::npos が返されます。

#include <iostream>
#include <string>

bool ends_with(const std::string& str, const std::string& suffix) {
  return str.find_last_of(suffix) == str.size() - suffix.size();
}

int main() {
  std::string str = "Hello, World!";
  std::string suffix = "World!";

  if (ends_with(str, suffix)) {
    std::cout << "The string ends with '" << suffix << "'" << std::endl;
  } else {
    std::cout << "The string does not end with '" << suffix << "'" << std::endl;
  }

  return 0;
}

長所

  • std::basic_string::ends_with よりも効率的な場合がある

短所

  • サフィックスが見つからない場合の処理が必要

正規表現を使用する

正規表現を使用して、文字列が特定のサフィックスで終わっているかどうかを判定することができます。以下のコード例では、std::regex クラスと std::regex_search 関数を使用して、サフィックスと一致するパターンを検索しています。

#include <iostream>
#include <string>
#include <regex>

bool ends_with(const std::string& str, const std::string& suffix) {
  std::regex regex(suffix + "$");
  return std::regex_search(str, regex);
}

int main() {
  std::string str = "Hello, World!";
  std::string suffix = "World!";

  if (ends_with(str, suffix)) {
    std::cout << "The string ends with '" << suffix << "'" << std::endl;
  } else {
    std::cout << "The string does not end with '" << suffix << "'" << std::endl;
  }

  return 0;
}

長所

  • 複雑なサフィックスパターンに対応できる

短所

  • 他 の方法よりも処理速度が遅い場合がある
  • 正規表現ライブラリのインクルードが必要