在 Qt 中,如何将 Unicode 代码点 U+1F64B 转换为包含等效字符“”的 QString?

In Qt, how do I convert the Unicode codepoint U+1F64B to a QString holding its equivalent character ""?

背景:

我正在创建一个散列,通过向它提供包含其字符的 QString,您可以查找下面看到的描述。

我得到了相关数据的完整列表,看起来像这样:

QHash<QString, QString> lookupCharacterDescription;
...
lookupCharacterDescription.insert("003F","QUESTION MARK");
lookupCharacterDescription.insert("0040","COMMERCIAL AT");
lookupCharacterDescription.insert("0041","LATIN CAPITAL LETTER A");
lookupCharacterDescription.insert("0042","LATIN CAPITAL LETTER B");
...
lookupCharacterDescription.insert("1F648","SEE-NO-EVIL MONKEY");
lookupCharacterDescription.insert("1F649","HEAR-NO-EVIL MONKEY");
lookupCharacterDescription.insert("1F64A","SPEAK-NO-EVIL MONKEY");
lookupCharacterDescription.insert("1F64B","HAPPY PERSON RAISING ONE HAND");
...
lookupCharacterDescription.insert("FFFD","REPLACEMENT CHARACTER");
lookupCharacterDescription.insert("FFFE","<not a character>");
lookupCharacterDescription.insert("FFFF","<not a character>");
lookupCharacterDescription.insert("FFFFE","<not a character>");
lookupCharacterDescription.insert("FFFFF","<not a character>");

现在显然 "1F64B" 需要在这里包裹一些东西。我试过把 0x1F64B 之类的东西当作 QChar,但老实说,我是在黑暗中摸索。我可以让它使用较低的值,如拉丁字母,但它无法使用 5 个字符的地址。

问题:

当您使用 QString(0x1F64B) 时,它会调用 QString::QString(QChar ch)。由于 QChar 是 16 位类型,它将 截断 值到 0xF64B 并且你得到一个无效字符,因为该代码点当前未分配。我很确定您会在那条线上收到超出范围的警告。如果放大或使用十六进制编辑器,您可以很容易地在字符 中看到值 F64B。由于 0x1F64B 无法放入单个 16 位 QChar 并且必须由代理项对表示,因此您不能以这种方式初始化字符串。

OTOH QString("") 有效,因为它是从另一个字符串 构造字符串。您必须使用这样的字符串构造字符串,或者通过分配 UTF-8/16 代码单元手动构造字符串。

Is this considered UTF-32?

没有。 UTF-32 是一种 Unicode 编码,它使用 32 位作为代码单元。你只有 QString 而不是一个裸字节数组,所以你不需要关心它的底层编码(实际上是 UTF-16)

What can I wrap this value "1F64B" in to produce the QString("")?

您不应将数值作为字符串处理。改为将其存储为数字类型

QHash<qint32, QString> lookupCharacterDescription;
lookupCharacterDescription.insert(0x1F64B, "HAPPY PERSON RAISING ONE HAND");

然后创建一个包含代码点 0x1F64B 处的字符的字符串使用

uint cp = 0x1F64B;
QString mystr = QString::fromUcs4(&cp, 1);

Will the wrappings also work for the lower values?

是的,自 UCS4 以来,A.K.A。 UTF-32,可以存储任何可能的Unicode字符

或者,您可以从 UTF-16 或 UTF-8 构建字符。 U+1F64B 在 UTF-16 中编码为 D83D DE4B,或在 UTF-8 中编码为 F0 9F 99 8B,因此您可以使用以下任何一种

QChar utf16[2] = { 0xD38D, 0xDE4B };
str1 = QString(utf16, 2);
char* utf8[4] = { 0xF0, 0x9F, 0x99, 0x8B };
str2 = QString::fromUtf8(utf8, 4);

如果您想在源代码中以其文字形式包含字符串,则以下任一方法都有效

str1 = QString::fromWCharArray(L"\xD83D\xDE4B");
str2 = QString::fromUtf8("\xF0\x9F\x99\x8B");

如果您有 C++11 支持,那么只需对 UTF-8、UTF-16 和 UTF-32 分别使用前缀 u8uU,例如

u8""
u""
U""
u8"\U0001F64B"
u"\U0001F64B"
u"\uD83D\uDE4B"
U"\U0001F64B" 

理解文本和编码的必读文章:There Ain't No Such Thing as Plain Text