質問

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

次のようにして、UTF-8でエンコードされた1,2および3バイトのUnicode文字をテストすることができます。

string in = "pi = \u3a0";

しかし、4バイトでエンコードされたUnicode文字を取得するにはどうすればよいですか?試しました:

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

私が理解している限り、出力すべきです。しかし、それを印刷するとᴶ 0

不足しているものは何ですか?

編集:

先行ゼロを追加することで機能するようになりました:

string in = "\U00010102";

もっと早くそれを考えていたらよかった:)

役に立ちましたか?

解決

\ u に4桁が続くのではなく、 \ U に8桁が続くパターンには、より長い形式のエスケープがあります。これは、特に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は次のようになります。

警告C4566:ユニバーサル文字名「\ UD800DD02」で表される文字は、現在のコードページ(932)で表すことができません

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

実行すると、プログラムは次を印刷します。

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

UTF-8バイト文字列とワイド文字列は正しいが、コンパイラは&quot; \ U00010102&quot; の変換に失敗し、バイト文字列&quot; ??&quot; 、誤った結果。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top