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>
を使うと効率的な場合があります。