[c++]文字列から1文字ずつ、サロゲートペアと異体字セレクタを考慮しつつ取り出す

Unicode文字列から「1文字ずつ」を取り出す場合、異体字セレクタやサロゲートペアを考慮に入れる必要がある。
以下、日本語環境での話(モンゴル文字の異体字セレクタ等は未対応)。

1.std::wstring(2バイト環境)の場合

以前の記事で書いたとおり、異体字セレクタは文字の末尾に4byte分の情報が付加される。(C++Builderで異体字セレクタを使う)

このため、wchar_tが2byteの場合、wstringの「1文字」が取り得るバイト数は以下の4通りになる。

「1文字」の4パターン バイト数
基本文字(基本多言語面) 2byte
サロゲートペア 4byte
基本文字の異体字セレクタ付 6byte
サロゲートペアの異体字セレクタ付 8byte

以下、文字列から、1文字ずつをstd::vectorに格納するメソッド。

(wchar_tが16bit/unsignedであることを前提にしたコード)

2.std::string(utf-8)の場合

utf-8文字列をstd::stringに突っ込んで使う場合もあるので(自分自身はやらないが)、ちょっと調べた。 以下のような方法で取り出せる(たぶん)。

utf-8文字は、先頭バイトを見ると1文字分のバイト数が分かるので、サロゲートペア判定は特に必要ない。 だが、そこで取れるバイト数には異体字セレクタ情報は反映されないので、自前で処理する必要がある。

文字に付加される異体字セレクタは計4byte分で、漢字用のIVSでは以下の範囲を取るようだ。

バイト順 値の範囲
0xF3 (固定)
0xA0 (固定)
0x84~0x87
0x80~0xBF
(0x80~0xAF)

4バイト目は、3バイト目が0x87の時に限り最大で0xAF(たぶん)。

以下、utf-8文字列の格納されたstd::stringから1文字ずつ取り出すメソッド。
なお、IVS最初の0xF3は、単体でも1byteで文字を表現するので、まず2byte分を判定する必要がある。

3.サンプルプログラム

C++Builderによるサンプルプログラム。

TFormにTEditとTMemoをひとつずつ、TButtonを2つ貼り付ける。
TEditとTMemoのフォントは游明朝、サイズを40にしておく。 TEditに以下の文字列を入れておく。

文字列の漢字部分は、最初の「辻」から順に
・基本文字
・異体字セレクタ
・基本文字
・サロゲートペア
・サロゲートペア
・サロゲートペアの異体字セレクタ付
英字は小文字のaが全角、大文字のAは半角。

3-1.std::wstringを使った例

Button1Clickを次のように実装。

結果:

3-2.std::stringを使った例

C++BuilderにはUTF8String型があるので、変換にはそれを使っている。
Button2Clickを以下のように実装。

結果:
 
以上、とりあえずのテストでは上手くいっているが、何か見落とし等があるかも。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です