Cpp 文字列リテラル
C++に戻る
本来の表記は「C++(Cpp) 文字列リテラル」です。この記事に付けられた題名はテンプレート:記事名の制約から不正確なものとなっています。 |
※このページではC++にのみ存在する機能として、記事タイトルがC++ 文字列リテラルになっています。
文字列リテラル
文字列リテラルのリテラル(Literal)とは英語で文字通りのという意味があります。プログラムでは文字列そのものを表す表現という意味でもあり、初期化や関数の引数で文字列を指定するときの表現となっています。C++ではダブルクォーテーションで囲うものが有名です。
通常リテラル " "
"abc"
はいはい。見たことあります。こういう表記ですね。みたことない?。そっかそっか。まだまだ知らない人もいるんだね。文字列を引数にとる関数を呼び出すときは、以下のようにも表記できるってことです。
function("abc");
おー。ダブルクォーテーションの使い方。これこれ。これを見たかったね。
ここからがこの記事の本番です。ダブルクォーテーションで囲うのなんて、みんな知ってるっつうのね。プログラムやったことある人ならね。このリテラルっていうものには、たくさんの種類が準備されているのが、C++なのです。それをここで全部知っていこうとする記事です。リテラル。深い!
wchar_t リテラル L" "
まずは、wchar_t型の引数の場合はこうですね。Unicodeの範囲が使えるよね。
function(L"日本語もハングル한국어もいけるニダっし、そのほかの謎の国際言語Киргиз тилиってね。");
このようにL""とするだけで使えます。
char wchar_t スイッチ リテラル _T(" ")
そしてマイクロソフトが考えた_TでUnicodeを使うプロジェクトの場合はL""と同じで、そうでないプロジェクトに対しては""で扱うみたいな方法があって
function(_T("Hello, World!"));
という記法です。これは以下の設定に従います。
Character Set (文字セット):
プロジェクトのプロパティを開きます。 「構成プロパティ」 -> 「詳細設定」 -> 「文字セット」 「文字セット」が「Unicode 文字セットを使用する」の場合、_T マクロはワイド文字列 (wchar_t型) に展開されます。
Preprocessor Definitions (プリプロセッサの定義):
_UNICODE マクロが定義されていることを確認します。 プロジェクトのプロパティ -> 「構成プロパティ」 -> 「C/C++」 -> 「プリプロセッサ」 -> 「前処理済みのディフェクト」 _UNICODE が含まれていることを確認します。
これらの設定によって、_T マクロは _UNICODE マクロの定義状態に基づいて、適切な文字列型に展開されます。
ね。いろいろあるでしょ。でも、ここまではまだ基本です。プログラマなら知っておいてよっていうレベルね。
まだまだあります。さきにいろいろな説明を省略してどんなものがあるかをずらっと並べます。
char8_t utf8 = u8'a' ;
char16_t utf16 = u'あ' ;
char32_t utf32 = U'あ' ;
function(R"(a
b
c)");
function(LR"(い
ろ
は)");
// string
auto str = "Hello, World!"s ;
// u8string
auto u8str = u8"こんにちは世界! Hello, World!"s ;
// u16string
auto u16str = u"こんにちは世界! Hello, World!"s ;
// u32string
auto u32str = U"こんにちは世界! Hello, World!"s ;
// wstring
auto wstr = L"こんにちは世界! Hello, World!"s ;
// string_view
auto str = "Hello, World!"sv ;
// u8string_view
auto u8str = u8"こんにちは世界! Hello, World!"sv ;
// u16string_view
auto u16str = u"こんにちは世界! Hello, World!"sv ;
// u32string_view
auto u32str = U"こんにちは世界! Hello, World!"sv ;
// wstring_view
auto wstr = L"こんにちは世界! Hello, World!"sv ;
ね。結構あるでしょ。知らないリテラルあった!って人は衝撃だよね。そう、標準でも知っておかないといけないリテラルは多いんです。これから少しづつ紹介します。
char8_t, char16_t, char32_t リテラル u8" ", u" ", U" "
同じUnicodeでもUTF-8、UTF-16、UTF-32の3種類のエンコードを使い分けることが出来ます。
char8_t utf8 = u8'あ' ;//UTF-8エンコードで0xE3 0x81 0x82。
char16_t utf16 = u'あ' ;//UTF-16エンコードで0x30 0x42
char32_t utf32 = U'あ' ;//UTF-32エンコードで0x00 0x00 0x30 0x42
//////// UTF-8のコードポイントを取得する処理 //////////////////
uint32_t utf8Code = 0;
int numBytes = 0;
// 初めのバイトから先頭ビットが1の数を数える
while ((utf8 & (0x80 >> numBytes)) != 0) {
numBytes++;
}
// 先頭バイトの情報を使ってコードポイントを取得
utf8Code = utf8 & (0xFF >> numBytes);
// 残りのバイトを処理
for (int i = 1; i < numBytes; i++) {
char8_t followByte = /* 残りのバイトを取得する処理 */;
utf8Code = (utf8Code << 6) | (followByte & 0x3F);
}
std::cout << "UTF-8 Code: 0x" << std::hex << utf8Code << std::endl;
//////// UTF-16のコードポイントを取得する処理 //////////////////
uint32_t utf16Code = static_cast<uint32_t>(utf16);
std::cout << "UTF-16 Code: 0x" << std::hex << utf16Code << std::endl;
//////// UTF-32のコードポイントを取得する処理 //////////////////
uint32_t utf32Code = static_cast<uint32_t>(utf32);
std::cout << "UTF-32 Code: 0x" << std::hex << utf32Code << std::endl;
この先もUnicodeのそれぞれのエンコードについて表現しますが、以降は、コードポイントがどうやって確認できるかという議論は省略します。
生文字列リテラル R"( )", LR"( )"
生文字列リテラルを指定すると改行文字も反映したリテラルというものが作れます。
const char* multilineChars = R"(a
b
c)";
const char* multilineWideChars = LR"(あい
こころ
おもい)";
multilineCharsはa\nb\ncで初期化されたのと同じことになります。LRとするとwchar_t型の初期化として使えます。
改行文字が反映できるだけでなく、全てエスケープシーケンスを無効化できる効果、連続した空白の保持といった効果も得られるのが生文字列リテラルの特徴です。
string リテラル " "s
string形式の初期化に使えるリテラルが " "s です。サンプルでは型推論で使いましたが、関数の引数がstringになっているときに明示して使うこともできます。
auto stringStr = "Hello, World"s;
wstring リテラル L" "s
日本語文字を使えるようにする wstring に対応するには L" "s を使います。
auto wstringStr = L"こんにちは!世界!Hello, World"s;
u8string リテラル u8" "s
日本語文字を使えるようにしつつUTF-8エンコードを使う u8string に対応するには u8" "s を使います。
auto wstringStr = u8"こんにちは!世界!Hello, World"s;
u16string リテラル u" "s
u32string リテラル U" "s
C++に戻る