5

さまざまなバイト長の utf-8 文字でテストする必要がある小さなアプリを作成しています。

たとえば、次のようにして、1、2、および 3 バイトの utf-8 でエンコードされた Unicode 文字を入力してテストできます。

string in = "pi = \u3a0";

しかし、どうすれば 4 バイトでエンコードされた Unicode 文字を取得できますか? 私が試してみました:

string in = "aegan check mark = \u10102";

私が理解している限り、出力する必要があります。しかし、それを印刷するとᴶ0になります

私は何が欠けていますか?

編集:

先行ゼロを追加して動作させました:

string in = "\U00010102";

もっと早く考えていればよかったです:)

4

1 に答える 1

6

\Uパターンには、4 桁ではなく 8 桁の長い形式のエスケープがあり\uます。これは、Java や Python などでも使用されています。

>>> '\xf0\x90\x84\x82'.decode("UTF-8")
u'\U00010102'

ただし、バイト文字列を使用している場合は、コンパイラに依存してエスケープを UTF-8 文字列に変換するのではなく、上記のように各バイトをエスケープしてみませんか? これは、次のプログラムをコンパイルすると、移植性も高くなるようです。

#include <iostream>
#include <string>

int main()
{
    std::cout << "narrow: " << std::string("\uFF0E").length() <<
        " utf8: " << std::string("\xEF\xBC\x8E").length() <<
        " wide: " << std::wstring(L"\uFF0E").length() << std::endl;

    std::cout << "narrow: " << std::string("\U00010102").length() <<
        " utf8: " << std::string("\xF0\x90\x84\x82").length() <<
        " wide: " << std::wstring(L"\U00010102").length() << std::endl;
}

私の現在のオプションを使用したwin32では、clは次のようになります。

warning C4566: character represented by universal-character-name '\UD800DD02' cannot be represented in the current code page (932)

コンパイラは、バイト文字列内のすべての Unicode エスケープをシステム コード ページに変換しようとしますが、UTF-8 とは異なり、すべての Unicode 文字を表すことはできません。奇妙なことに、それが UTF-16 (内部の Unicode 表現) であることを理解\U00010102\uD800\uDD02、エラー メッセージでエスケープを台無しにしました...

実行すると、プログラムは次のように出力します。

narrow: 2 utf8: 3 wide: 1
narrow: 2 utf8: 4 wide: 2

UTF-8 バイト文字列とワイド文字列は正しいのですが、コンパイラは を変換できず"\U00010102"、バイト文字列"??"が正しくない結果になることに注意してください。

于 2008-10-15T14:53:41.063 に答える