4バイトのUTF-8文字を入力するにはどうすればよいですか?
-
03-07-2019 - |
質問
バイト長の異なる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;
、誤った結果。