我需要屏蔽 wchar_t 并以 unicode (UTF-8) 表示形式输出
您是否阅读过UTF-8 in the Unicode standard(第 3.9 节 - Unicode 编码形式)或RFC 3629,甚至UTF-8 documentation on Wikipedia 的官方规范?
它们描述了将 21 位代码点编号拆分为编码字节序列所需的算法。请注意,wchar_t 在 Windows 上是 16 位 (UTF-16),但在大多数其他平台上是 32 位 (UTF-32)。 UTF 之间的转换相当简单,但您必须考虑 UTF 的实际含义,因为将 UTF-16 转换为 UTF-8 与将 UTF-32 转换为 UTF-8 有点不同。
简而言之,你需要这样的东西:
uint32_t codepoint = ...;
// This is the actual codepoint number, decoded from 1 or 2 wchar_t
// elements, depending on the UTF encoding of the wchar_t sequence.
// In UTF-32, the characters are the actual codepoint numbers as-is.
// In UTF-16, only the characters <= 0xFFFF are the actual codepoint
// numbers, the rest are encoded using surrogate pairs that you would
// have to decode to get the actual codepoint numbers...
uint8_t bytes[4];
int numBytes = 0;
if (codepoint <= 0x7F)
{
bytes[0] = (uint8_t) codepoint;
numBytes = 1;
}
else if (codepoint <= 0x7FF)
{
bytes[0] = 0xC0 | (uint8_t) ((codepoint >> 6) & 0x1F);
bytes[1] = 0x80 | (uint8_t) (codepoint & 0x3F);
numBytes = 2;
}
else if (codepoint <= 0xFFFF)
{
bytes[0] = 0xE0 | (uint8_t) ((codepoint >> 12) & 0x0F);
bytes[1] = 0x80 | (uint8_t) ((codepoint >> 6) & 0x3F);
bytes[2] = 0x80 | (uint8_t) (codepoint & 0x3F);
numBytes = 3;
}
else if (codepoint <= 0x10FFFF)
{
bytes[0] = 0xF0 | (uint8_t) ((codepoint >> 18) & 0x07);
bytes[1] = 0x80 | (uint8_t) ((codepoint >> 12) & 0x3F);
bytes[2] = 0x80 | (uint8_t) ((codepoint >> 6) & 0x3F);
bytes[3] = 0x80 | (uint8_t) (codepoint & 0x3F);
numBytes = 4;
}
else
{
// illegal!
}
// use bytes[] up to numBytes as needed...
这可以简化为:
uint32_t codepoint = ...; // decoded from wchar_t sequence...
uint8_t bytes[4];
int numBytes = 0;
if (codepoint <= 0x7F)
{
bytes[0] = 0x00;
numBytes = 1;
}
else if (codepoint <= 0x7FF)
{
bytes[0] = 0xC0;
numBytes = 2;
}
else if (codepoint <= 0xFFFF)
{
bytes[0] = 0xE0;
numBytes = 3;
}
else if (codepoint <= 0x10FFFF)
{
bytes[0] = 0xF0;
numBytes = 4;
}
else
{
// illegal!
}
for(int i = 1; i < numBytes; ++i)
{
bytes[numBytes-i] = 0x80 | (uint8_t) (codepoint & 0x3F);
codepoint >>= 6;
}
bytes[0] |= (uint8_t) codepoint;
// use bytes[] up to numBytes as needed...
在您的示例中,0000010010001110 是十进制 1166,十六进制 0x48E。 Codepoint U+048E 以 UTF-8 编码为字节 0xD2 0x8E,例如:
0000010010001110b -> 010010b 001110b
0xC0 或 010010b -> 0xD2
0x80 或 001110b -> 0x8E