C++でchar型の1文字をstd::string型へ変換する場合は、std::stringのコンストラクタを使う方法が基本です。
#include <iostream>
#include <string>
int main()
{
char c = 'A';
std::string str(1, c);
std::cout << str << '\n';
return 0;
}
実行結果は次のとおりです。
A
std::string str(1, c);の第1引数には文字数、第2引数には繰り返す文字を指定します。
この例では、文字cを1回並べた文字列を生成しているため、1文字だけを含むstd::stringになります。
charを1文字のstringに変換する書き方
基本構文は次のとおりです。
std::string 変数名(文字数, 文字);
1文字だけを変換する場合は、文字数に1を指定します。
char c = 'A';
std::string str(1, c);
この方法は、charを1文字の文字列へ変換していることが分かりやすく、初心者にもおすすめです。
同じ文字を複数回並べる方法
第1引数の値を増やすと、同じ文字を複数回並べた文字列を生成できます。
#include <iostream>
#include <string>
int main()
{
char c = 'A';
std::string str(5, c);
std::cout << str << '\n';
return 0;
}
実行結果は次のとおりです。
AAAAA
std::string str(5, c);は、文字cを5回並べた文字列を生成します。
一時的なstringとして使用する方法
変数へ保存せず、その場でstd::stringを生成することもできます。
#include <iostream>
#include <string>
int main()
{
char c = 'A';
std::cout << std::string(1, c) << '\n';
return 0;
}
関数の引数へ渡す場合にも使用できます。
#include <iostream>
#include <string>
void printString(const std::string& str)
{
std::cout << str << '\n';
}
int main()
{
char c = 'B';
printString(std::string(1, c));
return 0;
}
初期化リストでcharをstringに変換する方法
C++11以降では、波括弧を使った初期化リストからstd::stringを生成できます。
#include <iostream>
#include <string>
int main()
{
char c = 'A';
std::string str{c};
std::cout << str << '\n';
return 0;
}
実行結果は次のとおりです。
A
std::string str{c};は、文字cを1つだけ含む初期化リストから文字列を生成します。
丸括弧と波括弧の違い
次の2つは、どちらも1文字の文字列を生成します。
std::string str1(1, c);
std::string str2{c};
ただし、内部で選択されるコンストラクタは異なります。
std::string str1(1, c);
こちらは、文字cを指定回数だけ繰り返すコンストラクタを使用します。
std::string str2{c};
こちらは、std::initializer_list<char>を受け取るコンストラクタを使用します。
どちらも正しい書き方ですが、1文字の変換であることを明確に示したい場合は、std::string(1, c)が分かりやすいでしょう。
既存のstringにcharを追加する方法
すでに存在するstd::stringへ1文字を追加したい場合は、毎回新しい文字列を作る必要はありません。
+=演算子やpush_back()を使用できます。
+=演算子で末尾に追加する
#include <iostream>
#include <string>
int main()
{
std::string str = "ABC";
char c = 'D';
str += c;
std::cout << str << '\n';
return 0;
}
実行結果は次のとおりです。
ABCD
std::stringの+=演算子は、char型の文字を直接受け取れます。
短く分かりやすく記述できる方法です。
push_back関数で末尾に追加する
#include <iostream>
#include <string>
int main()
{
std::string str = "ABC";
char c = 'D';
str.push_back(c);
std::cout << str << '\n';
return 0;
}
push_back()は、文字列の末尾へ1文字を追加するためのメンバ関数です。
1文字を追加する処理であることを明確に示したい場合に適しています。
append関数で追加する
append()でも文字を追加できます。
#include <iostream>
#include <string>
int main()
{
std::string str = "ABC";
char c = 'D';
str.append(1, c);
std::cout << str << '\n';
return 0;
}
append(1, c)は、文字cを1回追加するという意味です。
ただし、1文字だけを末尾へ追加する場合は、+=またはpush_back()のほうが簡潔です。
charをstringへ代入する
既存のstd::stringの内容を、1文字だけに置き換えることもできます。
#include <iostream>
#include <string>
int main()
{
char c = 'A';
std::string str = "Hello";
str = c;
std::cout << str << '\n';
return 0;
}
実行結果は次のとおりです。
A
str = c;を実行すると、もともとの文字列は破棄され、cだけを含む長さ1の文字列になります。
新しく文字列を生成する場合は、std::string str(1, c);のほうが意図を把握しやすいでしょう。
char配列をstringに変換する方法
char型の1文字ではなく、複数の文字を格納したchar配列をstd::stringへ変換することもできます。
配列がヌル終端されているかどうかによって、書き方が異なります。
ヌル終端されたchar配列を変換する
#include <iostream>
#include <string>
int main()
{
char text[] = "Hello";
std::string str(text);
std::cout << str << '\n';
return 0;
}
実行結果は次のとおりです。
Hello
文字列リテラルから初期化したchar配列の末尾には、終端を表すヌル文字'\0'が格納されています。
std::stringのコンストラクタは、配列の先頭からヌル文字が現れるまでを文字列として読み込みます。
次のように代入形式で記述することもできます。
char text[] = "Hello";
std::string str = text;
const charポインタを変換する
C言語形式の文字列を指すconst char*も、std::stringへ変換できます。
#include <iostream>
#include <string>
int main()
{
const char* text = "Hello";
std::string str(text);
std::cout << str << '\n';
return 0;
}
この場合も、std::stringはヌル文字までを読み取って文字列を生成します。
文字数を指定して変換する
char配列がヌル終端されていない場合は、読み込む文字数を明示する必要があります。
#include <iostream>
#include <string>
int main()
{
char text[] = {'H', 'e', 'l', 'l', 'o'};
std::string str(text, 5);
std::cout << str << '\n';
return 0;
}
実行結果は次のとおりです。
Hello
この配列には終端を表す'\0'がありません。
そのため、std::string str(text, 5);のように、読み込む文字数を指定しています。
ヌル終端されていない配列に対して、次のように記述してはいけません。
std::string str(text);
ヌル文字が見つかるまで配列の範囲外を読み込む可能性があり、未定義動作につながります。
charポインタをstringへ変換するときの注意点
char*やconst char*からstd::stringを生成する場合は、ポインタが有効であることを確認する必要があります。
nullptrをstd::stringへ渡してはいけない
次のコードは不正です。
const char* text = nullptr;
std::string str(text);
std::string(const char*)は、有効なヌル終端文字列を指すポインタを前提としています。
nullptrを渡すと、正しい文字列を読み取れないため、動作は保証されません。
ポインタがnullptrになる可能性がある場合は、事前に確認します。
#include <iostream>
#include <string>
int main()
{
const char* text = nullptr;
std::string str = text != nullptr ? std::string(text) : std::string();
std::cout << str << '\n';
return 0;
}
より簡潔に書く場合は、次のように記述できます。
std::string str = text ? text : "";
textが有効ならその内容を使用し、nullptrなら空文字列を使用します。
ヌル文字とnullptrの違い
ヌル文字'\0'とヌルポインタnullptrは、まったく異なるものです。
char nullCharacter = '\0';
const char* nullPointer = nullptr;
'\0'は、数値として0の値を持つ1文字です。
C言語形式の文字列では、文字列の終端を表すために使われます。
一方、nullptrは、どのオブジェクトも指していないことを表すポインタ値です。
std::to_stringでcharを変換するときの注意点
数値を文字列へ変換する場合は、std::to_string()がよく使われます。
ただし、charを文字としてstd::stringへ変換したい場合には適していません。
std::to_stringでは文字コード値が変換される
#include <iostream>
#include <string>
int main()
{
char c = 'A';
std::string str = std::to_string(c);
std::cout << str << '\n';
return 0;
}
charは整数型の一種です。
std::to_string()にはchar専用のオーバーロードがないため、cは整数型へ昇格し、その数値が文字列化されます。
ASCII互換の文字コードを使用する一般的な環境では、'A'の値は65であるため、次のように表示されます。
65
ただし、C++規格はASCIIそのものを必須としているわけではないため、文字コード値は処理系に依存します。
文字'A'を文字列"A"へ変換したい場合は、次のように記述します。
std::string str(1, c);
charの数値を文字列にしたい場合
charが持つ整数値を文字列へ変換することが目的なら、std::to_string()を使用できます。
意図を明確にするため、intへ明示的に変換すると分かりやすくなります。
#include <iostream>
#include <string>
int main()
{
char c = 'A';
std::string str = std::to_string(static_cast<int>(c));
std::cout << str << '\n';
return 0;
}
charとstringを連結する方法
charとstd::stringを組み合わせて、新しい文字列を生成することもできます。
stringの末尾へcharを追加する
std::string str = "Hello";
char c = '!';
str += c;
結果は次の文字列になります。
Hello!
stringの先頭へcharを追加する
文字列の先頭へ1文字を追加する場合は、insert()を使用できます。
#include <iostream>
#include <string>
int main()
{
std::string str = "ello";
char c = 'H';
str.insert(str.begin(), c);
std::cout << str << '\n';
return 0;
}
実行結果は次のとおりです。
Hello
1文字のstd::stringを生成して連結する方法もあります。
std::string result = std::string(1, c) + str;
charとstringを新しい文字列として連結する
#include <iostream>
#include <string>
int main()
{
char c = 'A';
std::string str = "BC";
std::string result = std::string(1, c) + str;
std::cout << result << '\n';
return 0;
}
実行結果は次のとおりです。
ABC
先にstd::stringを生成することで、+演算子による文字列連結が行われます。
char同士を+演算子で連結できない理由
char同士を+演算子で加算しても、文字列の連結にはなりません。
char a = 'A';
char b = 'B';
auto result = a + b;
charは整数型なので、式の評価時に整数型へ昇格し、数値として加算されます。
ASCII互換環境では、'A'が65、'B'が66であるため、結果は整数の131になります。
複数のcharをstringとして連結する方法
複数のcharから文字列を作る場合は、std::stringへ順番に追加します。
#include <iostream>
#include <string>
int main()
{
char a = 'A';
char b = 'B';
std::string result;
result += a;
result += b;
std::cout << result << '\n';
return 0;
}
初期化リストを使う方法もあります。
std::string result{a, b};
この場合、aとbを順番に含む文字列が生成されます。
文字列リテラルとの加算に関する注意点
次のコードは、"ABC"を生成する処理にはなりません。
char c = 'A';
auto result = c + "BC";
文字列リテラル"BC"は、式の中では先頭要素を指すconst char*へ変換されます。
そこへcharの整数値を加えるため、文字列連結ではなくポインタ演算が行われます。
ASCII互換環境でcが'A'の場合は、ポインタを65要素先へ進めようとします。
文字列リテラルの配列範囲を大きく外れるため、通常は未定義動作になります。
安全に文字列を連結する方法
先にcharをstd::stringへ変換します。
std::string result = std::string(1, c) + "BC";
次のように、文字列を生成してから追加しても構いません。
std::string result{c};
result += "BC";
数字のcharを変換する方法
数字を表すcharを扱う場合は、文字列へ変換したいのか、数値へ変換したいのかを区別する必要があります。
文字の’5’を文字列の”5″に変換する
char c = '5';
std::string str(1, c);
結果は文字列の"5"です。
数値の5を文字列の”5″に変換する
整数値を文字列へ変換する場合は、std::to_string()を使用します。
int number = 5;
std::string str = std::to_string(number);
文字の’5’を整数の5に変換する
数字を表す文字から'0'を引くと、対応する整数値を取得できます。
char c = '5';
int number = c - '0';
ただし、cが数字であることを事前に確認する必要があります。
#include <cctype>
#include <iostream>
int main()
{
char c = '5';
if (std::isdigit(static_cast<unsigned char>(c)))
{
int number = c - '0';
std::cout << number << '\n';
}
return 0;
}
一般的なcharは、処理系によって符号付きになることがあります。
負の値を持つcharをそのままstd::isdigit()へ渡すと問題が起こる可能性があります。
そのため、unsigned charへ変換してから渡すのが安全です。
ヌル文字をstringに変換した場合
char型には、ヌル文字'\0'を格納できます。
char c = '\0';
std::string str(1, c);
この場合、strは空文字列ではありません。
長さ1の文字列であり、内部にヌル文字を1つ保持しています。
#include <iostream>
#include <string>
int main()
{
char c = '\0';
std::string str(1, c);
std::cout << str.size() << '\n';
return 0;
}
実行結果は次のとおりです。
1
ヌル文字は画面に表示されないため、文字列を出力しても何も表示されていないように見えます。
空文字列との違い
次の2つは異なる文字列です。
std::string str1;
std::string str2(1, '\0');
str1.size()は0です。
str2.size()は1です。
std::stringは内部にヌル文字を含められるため、ヌル文字が含まれていることと、文字列が空であることは同じではありません。
複数のcharからstringを作る方法
複数のchar変数から1つの文字列を作る方法はいくつかあります。
初期化リストを使用する
#include <iostream>
#include <string>
int main()
{
char a = 'A';
char b = 'B';
char c = 'C';
std::string str{a, b, c};
std::cout << str << '\n';
return 0;
}
実行結果は次のとおりです。
ABC
push_backを繰り返す
#include <iostream>
#include <string>
int main()
{
char a = 'A';
char b = 'B';
char c = 'C';
std::string str;
str.push_back(a);
str.push_back(b);
str.push_back(c);
std::cout << str << '\n';
return 0;
}
文字を順番に追加しながら文字列を構築したい場合に適しています。
char配列から生成する
#include <iostream>
#include <string>
int main()
{
char chars[] = {'A', 'B', 'C'};
std::string str(chars, 3);
std::cout << str << '\n';
return 0;
}
この配列にはヌル文字がないため、文字数として3を指定しています。
ループ内でcharをstringへ追加する方法
文字を1文字ずつ処理しながら文字列を作る場合は、既存のstd::stringへpush_back()で追加する方法が自然です。
#include <iostream>
#include <string>
int main()
{
std::string source = "Hello";
std::string result;
for (char c : source)
{
result.push_back(c);
}
std::cout << result << '\n';
return 0;
}
毎回std::string(1, c)を生成して連結するよりも、直接追加するほうが処理の意図が明確です。
reserve関数で容量を確保する
完成する文字列の長さが事前に分かっている場合は、reserve()で容量を確保できます。
#include <iostream>
#include <string>
int main()
{
std::string source = "Hello";
std::string result;
result.reserve(source.size());
for (char c : source)
{
result.push_back(c);
}
std::cout << result << '\n';
return 0;
}
reserve()を使用すると、文字列の拡張時に発生するメモリ再確保の回数を減らせる可能性があります。
charと文字コードに関する注意点
charは1バイトの整数型です。
ただし、1つのcharが常に人間にとっての1文字を表すとは限りません。
英数字は1つのcharで扱えることが多い
英字や数字など、実行環境の文字コードで1バイトに収まる文字は、通常、1つのcharで扱えます。
char c = 'A';
このような文字であれば、std::string(1, c)で問題なく1文字の文字列を生成できます。
日本語は1つのcharに格納できないことが多い
UTF-8では、ひらがなや漢字の多くが複数バイトで表現されます。
そのため、通常のchar変数1つに日本語の1文字を格納することはできません。
次のようなコードは使用しないでください。
char c = 'あ';
このコードはコンパイルエラーになるか、複数文字リテラルとして実装依存の値になる可能性があります。
さらに、その値をcharへ代入すると、値が切り詰められる可能性もあります。
日本語の「あ」を安全に表すコードにはなりません。
std::stringは文字コードを管理しない
次のように文字列リテラルを使用することはできます。
std::string str = "あ";
ただし、通常の文字列リテラル"あ"がどの文字コードになるかは、コンパイラやコンパイル設定に依存します。
通常リテラルエンコーディングがUTF-8に設定されている場合、std::stringにはUTF-8のバイト列が格納されます。
この場合、多くの環境では"あ"は3バイトで表現されるため、str.size()は3になります。
#include <iostream>
#include <string>
int main()
{
std::string str = "あ";
std::cout << str.size() << '\n';
return 0;
}
std::string::size()が返すのは、人間が認識する文字数ではなく、格納しているchar要素の数です。
std::string自体は、UTF-8やShift_JISなどの文字コードを自動的に判別したり管理したりするクラスではありません。
C++20以降でUTF-8を扱うときの注意点
C++20以降では、UTF-8文字列リテラルu8"..."の型が変更されています。
u8文字列リテラルはchar8_t配列になる
C++17以前では、u8"あ"はconst charの配列でした。
C++20以降では、const char8_tの配列になります。
そのため、C++20以降では次のコードをそのまま使用できません。
std::string str = u8"あ";
std::stringはcharを要素とする文字列であり、u8"あ"はchar8_tの配列だからです。
std::u8stringを使用する
C++20以降でUTF-8コード単位を扱う場合は、std::u8stringを使用できます。
#include <string>
int main()
{
std::u8string str = u8"あ";
}
ただし、std::u8stringをそのままstd::coutへ出力することはできません。
表示や外部APIとの連携では、使用するライブラリや入出力先に応じた変換処理が必要です。
よくある間違い
charからstd::stringへ変換するときは、見た目が似ていても危険な書き方があります。
charのアドレスをそのまま渡す
次のコードは安全ではありません。
char c = 'A';
std::string str(&c);
&cはchar*なので、std::string(const char*)が呼び出されます。
このコンストラクタは、ポインタが指す位置からヌル文字が見つかるまで読み込みます。
しかし、変数cの直後に'\0'が存在する保証はありません。
そのため、変数の範囲外までメモリを読み込む可能性があり、未定義動作につながります。
1文字を変換する場合は、次のように記述します。
std::string str(1, c);
文字数を明示する次の書き方も有効です。
std::string str(&c, 1);
ただし、1文字の変換では、std::string(1, c)のほうが分かりやすいでしょう。
std::to_stringを使う
char c = 'A';
std::string str = std::to_string(c);
このコードでは、文字列"A"ではなく、charが持つ整数値が文字列化されます。
文字として変換する場合は、次のようにします。
std::string str(1, c);
char同士を加算する
char a = 'A';
char b = 'B';
auto result = a + b;
この処理は文字列連結ではなく、整数の加算です。
文字列として連結する場合は、次のように記述します。
std::string result{a, b};
charと文字列リテラルを直接加算する
char c = 'A';
auto result = c + "BC";
この処理は文字列連結ではなく、ポインタ演算になります。
配列の範囲外を指すポインタが生成される可能性が高く、未定義動作になります。
次のように、先にstd::stringを生成してください。
std::string result = std::string(1, c) + "BC";
用途別のおすすめ方法
目的によって適切な書き方は異なります。
charを1文字のstringに変換する場合
char c = 'A';
std::string str(1, c);
もっとも基本的で、意図が明確な方法です。
C++11以降で短く書く場合
char c = 'A';
std::string str{c};
初期化リストを使って1文字の文字列を生成します。
既存のstringの末尾へ追加する場合
str.push_back(c);
または次のようにします。
str += c;
既存のstringを1文字だけに置き換える場合
str = c;
ヌル終端されたchar配列を変換する場合
std::string str(charArray);
ヌル終端されていないchar配列を変換する場合
std::string str(charArray, length);
複数のcharからstringを作る場合
std::string str{a, b, c};
まとめ
C++でchar型の1文字をstd::stringへ変換する場合は、次の書き方が基本です。
char c = 'A';
std::string str(1, c);
C++11以降であれば、初期化リストを使うこともできます。
std::string str{c};
既存の文字列へ1文字を追加するだけなら、新しい文字列を生成する必要はありません。
str += c;
または、次のように記述します。
str.push_back(c);
std::to_string(c)は、文字そのものではなくcharの整数値を文字列化します。
そのため、"A"のような1文字の文字列を作る用途には適していません。
また、std::string(&c)はヌル終端が保証されないため、未定義動作につながる可能性があります。
1文字の変換には、安全で意図が分かりやすいstd::string(1, c)を使用するのがおすすめです。
以上、C++でcharをstringに変換する方法についてでした。
最後までお読みいただき、ありがとうございました。
