C++ “Ü”的UTF编码返回3个字节,而不是“实”unicode

C++ “Ü”的UTF编码返回3个字节,而不是“实”unicode,c++,unicode,encoding,utf-8,C++,Unicode,Encoding,Utf 8,我在玩下面提到的代码: 因为我在用TinyXML编写正确的UTF8XML时遇到了问题 我需要用DIAERESIS对拉丁文大写字母U进行编码,这是正确地写入XML等 以下是上面帖子的代码: std::string codepage_str = "Ü"; int size = MultiByteToWideChar( CP_ACP, MB_COMPOSITE, codepage_str.c_str(), codepage_str.len

我在玩下面提到的代码: 因为我在用TinyXML编写正确的UTF8XML时遇到了问题

我需要用DIAERESIS对拉丁文大写字母U进行编码,这是正确地写入XML等

以下是上面帖子的代码:

std::string codepage_str = "Ü";
int size = MultiByteToWideChar( CP_ACP, MB_COMPOSITE, codepage_str.c_str(),
                                codepage_str.length(), nullptr, 0 );
std::wstring utf16_str( size, '\0' );
MultiByteToWideChar( CP_ACP, MB_COMPOSITE, codepage_str.c_str(),
                     codepage_str.length(), &utf16_str[ 0 ], size );

int utf8_size = WideCharToMultiByte( CP_UTF8, 0, utf16_str.c_str(),
                                     utf16_str.length(), nullptr, 0,
                                     nullptr, nullptr );
std::string utf8_str( utf8_size, '\0' );
WideCharToMultiByte( CP_UTF8, 0, utf16_str.c_str(),
                     utf16_str.length(), &utf8_str[ 0 ], utf8_size,
                     nullptr, nullptr );
结果是一个std::string,大小为3,字节如下:

-       utf8_str    "Ü"   std::basic_string<char,std::char_traits<char>,std::allocator<char> >
        [size]  0x0000000000000003  unsigned __int64
        [capacity]  0x000000000000000f  unsigned __int64
        [0] 0x55 'U'    char
        [1] 0xcc 'Ì'    char
        [2] 0x88 'ˆ'    char
当我将其写入utf8文件时。十六进制值保留在那里:0x55 0xCC 0x88,记事本++向我显示正确的字符

然而,当我通过记事本++向文件中添加另一个Ü并再次保存它时,新写入的Ü显示为0xC3 0x9C,这是我最初预期的

我不明白,为什么我得到这个字符的3字节表示,而不是预期的unicode代码点U+00DC


尽管Notepad++正确地显示了它,但我们的专有系统将0xC3 0x 9C呈现为Ü,并通过呈现Ü而在0x55 0xCC 0x88上中断,因为无法将其识别为双字节utf 8

Unicode是复杂的。获得Ü的方法至少有两种:

带分音符的拉丁文大写字母U是Unicode代码点U+00DC

拉丁文大写字母U是Unicode代码点U+0055,组合分音符是Unicode代码点U+0308

U+00DC和U+0055 U+0308均显示为Ü

在UTF-8中,Unicode码点U+00DC编码为0xC3 0x9C,U+0055编码为0x55,U+0308编码为0xCC 0x88

您的专有系统似乎有一个bug


编辑:要获得您期望的内容,根据,请使用MB_预合成而不是MB_合成。

Unicode很复杂。获得Ü的方法至少有两种:

带分音符的拉丁文大写字母U是Unicode代码点U+00DC

拉丁文大写字母U是Unicode代码点U+0055,组合分音符是Unicode代码点U+0308

U+00DC和U+0055 U+0308均显示为Ü

在UTF-8中,Unicode码点U+00DC编码为0xC3 0x9C,U+0055编码为0x55,U+0308编码为0xCC 0x88

您的专有系统似乎有一个bug


编辑:为了得到您期望的结果,根据,使用MB_PRECOMPOSED而不是MB_COMPOSITE。

虽然编码输出在技术上是正确的,但您可以通过使用NFC表单解决专有系统中的问题

在NFC形式中,首先分解所有字符,例如,如果对Ü使用代码点U+00DC,它将分解为序列U+0055 U+0308,然后在示例中重新组合为它们的规范表示形式,如U+00DC


在Win32 API中,请参阅函数。

虽然编码输出在技术上是正确的,但您可以使用NFC表单在专有系统中解决此问题

在NFC形式中,首先分解所有字符,例如,如果对Ü使用代码点U+00DC,它将分解为序列U+0055 U+0308,然后在示例中重新组合为它们的规范表示形式,如U+00DC


在Win32 API中,请参阅函数。

此外,这些不同窗体之间的转换称为。此外,这些不同窗体之间的转换称为。