コンテンツにスキップ

C++/文字列とstd::string

出典: フリー教科書『ウィキブックス(Wikibooks)』
< C++

文字列とは

[編集]

文字列の基本概念

[編集]

文字列は文字の並びであり、テキストデータを表現するために使用されます。文字列は一連の文字コード(例えばASCIIやUnicode)で表されます。C++では、文字列は配列やクラスを使って表現されます。

文字列の表現方法

[編集]
Cスタイル文字列
文字列はchar配列を使って表現され、ヌル文字('\0')で終端されます。
char str[] = "Hello";
C++スタイル文字列
std::stringクラスを使用します。std::stringは、より多くの機能と簡便な操作方法を提供します。
std::string str{"Hello"};

C言語における文字列操作

[編集]

文字列リテラル

[編集]

文字列リテラルはダブルクォートで囲まれた文字列です。文字列リテラルは自動的にヌル終端が追加されます。例えば、"Hello, World!"Hello, World!\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"

文字列のイテレーション

[編集]

文字列のイテレーションと反復処理

[編集]

beginendを使って文字列をイテレートできます。

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