C++/文字列とstd::string
文字列とは
[編集]文字列の基本概念
[編集]文字列は文字の並びであり、テキストデータを表現するために使用されます。文字列は一連の文字コード(例えばASCIIやUnicode)で表されます。C++では、文字列は配列やクラスを使って表現されます。
文字列の表現方法
[編集]- Cスタイル文字列
- 文字列は
char配列を使って表現され、ヌル文字('\0')で終端されます。- 例
char str[] = "Hello";。
- C++スタイル文字列
std::stringクラスを使用します。std::stringは、より多くの機能と簡便な操作方法を提供します。- 例
std::string str{"Hello"};。
C言語における文字列操作
[編集]文字列リテラル
[編集]文字列リテラルはダブルクォートで囲まれた文字列です。文字列リテラルは自動的にヌル終端が追加されます。例えば、"Hello, World!"はH、e、l、l、o、,、 、W、o、r、l、d、!、\0の14文字からなります。
文字列関数の基本
[編集]C言語では、標準ライブラリの関数を使って文字列を操作します。
strlen- 文字列の長さを返します。
char str[] = "Hello"; size_t length = strlen(str); // lengthは5
strcpy- 文字列をコピーします。
char dest[10]; strcpy(dest, str); // destは"Hello"になる
strcat- 文字列を連結します。
char str1[20] = "Hello"; char str2[] = " World"; strcat(str1, str2); // str1は"Hello World"になる
std::stringの導入
[編集]std::stringの基本的な使い方
[編集]std::stringは標準ライブラリが提供する文字列クラスで、多くの便利なメソッドを持ちます。std::stringは動的にメモリを管理し、ヌル終端を気にせずに文字列操作が可能です。
std::string str{"Hello, World!"};
文字列の生成と初期化
[編集]- デフォルトコンストラクタ
std::string str;
- リテラルからの初期化
std::string str{"Hello"};
- 繰り返し文字からの初期化
std::string str(10, 'A'); // "AAAAAAAAAA"
文字列の操作
[編集]文字列の結合
[編集]std::stringでは+演算子やappendメソッドを使用して文字列を結合できます。
std::string str1{"Hello"}; std::string str2{"World"}; std::string result = str1 + " " + str2; // "Hello World"
または、
str1.append(" ").append(str2); // str1は"Hello World"になる
文字列の比較
[編集]==や!=、compareメソッドを使って文字列を比較できます。
if (str1 == str2) { // 同じ文字列 } else if (str1 != str2) { // 異なる文字列 } int result = str1.compare(str2); if (result == 0) { // 同じ文字列 } else if (result < 0) { // str1はstr2より小さい } else { // str1はstr2より大きい }
文字列の探索
[編集]findメソッドを使って文字列内の部分文字列を検索できます。
size_t pos = str.find("World"); if (pos != std::string::npos) { // "World" が見つかりました }
文字列の変換
[編集]文字列から数値への変換
[編集]std::stoi, std::stofなどの関数を使って変換できます。
int inum = std::stoi("123"); double dnum = std::stof("123.45");
数値から文字列への変換
[編集]std::to_stringを使います。
std::string str = std::to_string(123); // "123" std::string fstr = std::to_string(123.45); // "123.450000"
文字列のイテレーション
[編集]文字列のイテレーションと反復処理
[編集]beginとendを使って文字列をイテレートできます。
std::string str{"Hello"}; for (char c : str) { std::cout << c << std::endl; }
または、
for (std::string::iterator it = str.begin(); it != str.end(); ++it) { std::cout << *it << std::endl; }
文字列のスライスと部分文字列
[編集]文字列の部分文字列の取得
[編集]substrメソッドを使って部分文字列を取得できます。
std::string str{"Hello, World!"}; std::string sub = str.substr(0, 5); // "Hello"
文字列のスライス操作
[編集]substrメソッドを使うことで、任意の範囲の部分文字列を取得できます。
std::string slice = str.substr(7, 5); // "World"
C++20の新機能
[編集]std::string_viewの導入と利用
[編集]std::string_viewは軽量な文字列のビューを提供し、コピーせずに文字列を参照できます。
std::string_view sv = "Hello, World!";
std::string_viewは範囲ベースのループやsubstrのような操作を効率的に行えます。
std::formatを使った文字列フォーマット
[編集]std::formatはPythonのf-stringに似たフォーマット機能を提供します。
std::string str = std::format("Hello, {}!", "World"); // "Hello, World!"
コンセプトを使用した文字列操作関数のテンプレート化
[編集]C++20のコンセプトを使って、テンプレート関数のパラメータを制約し、より安全なコードを書くことができます。
template <typename T> concept StringLike = requires(T a) { { a.size() } -> std::convertible_to<std::size_t>; { a.data() } -> std::convertible_to<const char*>; }; template <StringLike T> void print_string(const T& str) { std::cout << str << std::endl; }
文字列の高度な操作
[編集]正規表現を用いた文字列操作
[編集]std::regexを使って正規表現による文字列操作を行います。
#include <regex> std::string str{"example.txt"}; std::regex re("([a-z]+)\\.txt"); std::smatch match; if (std::regex_search(str, match, re)) { std::cout << "Match: " << match[1] << std::endl; // "example" }
文字列の分割とトークン化
[編集]std::getlineを使って文字列を分割できます。
#include <sstream> std::string str{"Hello World"}; std::istringstream iss(str); std::string word; while (iss >> word) { std::cout << word << std::endl; }
文字列のパフォーマンスと最適化
[編集]文字列操作の効率的な実装方法
[編集]効率的なアルゴリズムとデータ構造を使って文字列操作を最適化します。例えば、文字列連結を繰り返す場合、std::ostringstreamを使うことで効率を向上させることができます。
#include <sstream> std::ostringstream oss; oss << "Hello" << " " << "World"; std::string result = oss.str(); // "Hello World"
メモリ使用量の最適化
[編集]std::stringの内部実装とメモリ管理について理解し、効率的なコードを書く方法を学びます。例えば、reserveメソッドを使って、必要なメモリを事前に確保することで再アロケーションを減らすことができます。
std::string str; str.reserve(100); // 100文字分のメモリを確保
文字列処理のベストプラクティス
[編集]エラーハンドリングと例外処理
[編集]文字列操作中のエラーを適切に処理する方法を学びます。
try { int num = std::stoi("abc"); } catch (const std::invalid_argument& e) { std::cerr << "Invalid argument: " << e.what() << std::endl; } catch (const std::out_of_range& e) { std::cerr << "Out of range: " << e.what() << std::endl; }
文字列操作のパフォーマンスの向上に向けた最善のアプローチ
[編集]ベストプラクティスを学び、効率的なコードを書けるようにします。例えば、頻繁に連結や削除が発生する場合は、std::stringの代わりにstd::deque<char>を使うと効率的な場合があります。