C++ Strings: std::basic_string::cbeginとstd::basic_string::beginの違いを解説


"std::basic_string::cbegin" は、C++ の標準ライブラリで提供されている std::basic_string クラスのメンバ関数の一つです。この関数は、文字列の先頭要素を指す const_iterator 型のイテレータを返します。const_iterator は、読み取り専用のイテレータであり、文字列の内容を変更することはできません。

"std::basic_string::cbegin" の役割

"std::basic_string::cbegin" は、文字列を反復処理する際に使用されます。例えば、文字列の各文字をループで処理したい場合などに便利です。

"std::basic_string::cbegin" の使い方

"std::basic_string::cbegin" の使い方は、以下の例のように非常に簡単です。

#include <iostream>
#include <string>

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

  for (auto it = str.cbegin(); it != str.cend(); ++it) {
    std::cout << *it;
  }

  std::cout << std::endl;

  return 0;
}

このコードを実行すると、以下の出力が得られます。

Hello, World!

"std::basic_string::cbegin" と "std::basic_string::begin" の違い

"std::basic_string::cbegin" と "std::basic_string::begin" は、どちらも文字列の先頭要素を指すイテレータを返しますが、以下の点が異なります。

  • 文字列の変更
    • "std::basic_string::cbegin": 返されるイテレータは読み取り専用であり、文字列の内容を変更することはできない
    • "std::basic_string::begin": 返されるイテレータは読み書き可能であり、文字列の内容を変更できる
  • 返されるイテレータの種類
    • "std::basic_string::cbegin": const_iterator 型のイテレータを返す
    • "std::basic_string::begin": iterator 型のイテレータを返す (const 修飾されていない)

"std::basic_string::cbegin" は、C++ の "Strings" を操作する際に便利なメンバ関数です。文字列を反復処理したい場合などに使用すると便利です。

  • "std::basic_string::cbegin" は、const 修飾された std::basic_string オブジェクトに対しても使用できます。
  • "std::basic_string::cbegin" は、C++11 以降で使用できる機能です。


文字列の各文字をループで処理する

#include <iostream>
#include <string>

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

  for (auto it = str.cbegin(); it != str.cend(); ++it) {
    std::cout << *it;
  }

  std::cout << std::endl;

  return 0;
}
Hello, World!

文字列の各文字を大文字に変換する

#include <iostream>
#include <string>

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

  for (auto it = str.cbegin(); it != str.cend(); ++it) {
    *it = std::toupper(*it);
  }

  std::cout << str << std::endl;

  return 0;
}
HELLO, WORLD!

文字列内の特定の文字をすべて別の文字に置き換える

#include <iostream>
#include <string>

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

  for (auto it = str.cbegin(); it != str.cend(); ++it) {
    if (*it == 'l') {
      *it = 'X';
    }
  }

  std::cout << str << std::endl;

  return 0;
}
HeXXo, WorX!d!

文字列から特定の部分文字列を抽出する

#include <iostream>
#include <string>

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

  std::string sub_str = str.substr(7, 5); // "World" を抽出

  std::cout << sub_str << std::endl;

  return 0;
}
World
#include <iostream>
#include <string>

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

  for (auto it = str.crbegin(); it != str.crend(); --it) {
    std::cout << *it;
  }

  std::cout << std::endl;

  return 0;
}
!dlroW ,olleH


代替方法

"std::basic_string::cbegin" の代替方法としては、以下のようなものがあります。

"std::basic_string::begin" を使う

"std::basic_string::begin" は、"std::basic_string::cbegin" と同様に文字列の先頭要素を指すイテレータを返しますが、以下の点が異なります。

  • 文字列の変更
    • "std::basic_string::cbegin": 返されるイテレータは読み取り専用であり、文字列の内容を変更することはできない
    • "std::basic_string::begin": 返されるイテレータは読み書き可能であり、文字列の内容を変更できる
  • 返されるイテレータの種類
    • "std::basic_string::cbegin": const_iterator 型のイテレータを返す (読み取り専用)
    • "std::basic_string::begin": iterator 型のイテレータを返す (読み書き可能)

範囲ベース for ループを使う

範囲ベース for ループを使用すると、"std::basic_string" の各要素を個別に処理することができます。この場合、イテレータを明示的に取得する必要はありません。

#include <iostream>
#include <string>

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

  for (char c : str) {
    std::cout << c << " ";
  }

  std::cout << std::endl;

  return 0;
}
H e l l o ,  W o r l d ! 

"std::at" 関数を使う

"std::at" 関数を使用すると、文字列の特定のインデックスにある要素にアクセスすることができます。

#include <iostream>
#include <string>

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

  for (int i = 0; i < str.size(); ++i) {
    std::cout << str.at(i) << " ";
  }

  std::cout << std::endl;

  return 0;
}
H e l l o ,  W o r l d ! 

"std::copy" アルゴリズムを使う

"std::copy" アルゴリズムを使用すると、文字列の内容を別の場所へコピーすることができます。

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

int main() {
  std::string str = "Hello, World!";
  char buf[13];

  std::copy(str.begin(), str.end(), buf);
  buf[12] = '\0';

  std::cout << buf << std::endl;

  return 0;
}
Hello, World!
  • それぞれの方法のメリットとデメリットを理解した上で、適切な方法を選択することが重要です。
  • 使用する代替方法は、処理内容やパフォーマンス要件によって異なります。