在 C++ 程序中使用 unicode

using unicode in a C++ program

我希望在我的文件同步器应用程序中正确处理带有 Unicode 字符的字符串,但我不知道这种编码是如何工作的?

在 unicode 字符串中,我可以看到 unicode 字符具有这种形式:"\uxxxx" 其中 xs 是数字,普通的 C 或 C++ 程序如何解释这种字符? (为什么'\'后面有一个'u'?有什么作用?)

在互联网上,我看到使用“宽字符串或 wchar_t ?? 那么,什么是适合处理 unicode 字符的对象呢?在 rapidJson(支持 Unicode、UTF-8、UTF-16、UTF-32)中,我们可以使用 const char* 来存储一个 JSOn 可以有 "wide characters" 但这些字符占用超过一个字节被代表...我不明白...

这是我暂时找到的那种临时安排(unicode->utf8?ascii?,listFolder是一个std::string):

boost::replace_all(listFolder, "\u00e0", "à");
boost::replace_all(listFolder, "\u00e2", "â");
boost::replace_all(listFolder, "\u00e4", "ä");
...

在 C++ 中处理 Unicode 字符串的合适对象是 icu::UnicodeString(检查边栏中的 "API References, ICU4C"),至少如果你真的想 handle Unicode 字符串(而不是将它们从应用程序的一个点传递到另一个点)。

wchar_t 是处理国际字符集的早期尝试,后来证明是失败的,因为一旦 Unicode 扩展到代码之外,微软将 wchar_t 定义为两个字节就不够用了点 0x10000。 Linux 将 wchar_t 定义为四个字节,但不一致使得它(及其派生的 std::wstring)对于可移植编程来说相当无用。

TCHAR 是一个 Microsoft 定义,默认情况下解析为 char,如果定义了 UNICODE,则解析为 WCHAR,而 WCHAR 又是 wchar_t 在间接层之后...是的。

C++11 给我们带来了 char16_tchar32_t 以及相应的字符串 类,但它们仍然是 basic_string<> 的实例,因此有他们的缺点,例如当尝试转换具有多个替换字符的大写/小写字符时(例如,德语 ß 需要扩展为大写的 SS;标准库不能这样做)。

另一方面,ICU 全力以赴。例如,它提供了标准字符串所没有的规范化和分解。


\uxxxx\UXXXXXXXX 是 unicode 字符转义。 xxxx是一个16位的十六进制数,表示一个UCS-2码位,相当于Basic Multilingual Plane中的一个UTF-16码位。 =43=]

XXXXXXXX是一个32位的十六进制数,代表一个UTF-32码位,可以是任意平面。

这些字符转义的处理方式取决于它们出现的上下文(例如,窄/宽字符串),这使得它们有些不完美。

C++11 引入了"proper" Unicode 文字:

u8"..." 在 UTF-8 编码中 总是 一个 const char[] .

u"..." 在 UTF-16 编码中 总是 一个 const uchar16_t[] .

U"..." 总是一个const uchar32_t[] UTF-32编码.

如果您在这三个之一中使用 \uxxxx\UXXXXXXXX,字符文字将始终扩展为正确的代码单元序列。


请注意,将 UTF-8 存储在 std::string 是可能的 ,但很危险。您需要注意很多事情:.length() 不是字符串中的字符数。 .substr() 可能导致部分序列和无效序列。 .find_first_of() 将无法按预期工作。等等。

也就是说,在我看来,UTF-8 是唯一任何 存储文本的合理编码选择。在某些情况下,将文本作为内存中的 UTF-16 处理(ICU 的方式),但在文件中,除了 UTF-8 之外不接受任何内容。它 space 高效,与字节序无关,并且允许即使是完全不知道 Unicode 问题的软件也能进行半正常的处理(参见上面的注意事项)。

In a unicode string, I can see that a unicode char has this form : "\uxxxx" where xs are numbers, how a normal C or C++ program interpret this kind of char ? (why there is a 'u' after '\' ? what's the effect ?)

这是一个unicode字符转义序列。它将被解释为 unicode 字符。转义字符后的 u 是语法的一部分,也是它与其他转义序列的区别所在。阅读 documentation 了解更多信息。

So, what's the suitable object to handle unicode characters ?

  • char 用于 uft-8
  • char16_t 用于 utf-16
  • char32_t 为 utf-32
  • wchar_t 的大小取决于平台,因此您不能对它适合哪种编码做出可移植的假设。

we can use const char* to store a JSOn that could have "wide characters" but those characters take more than a byte to be represented...

如果您的意思是可以在 char 字符串中存储多字节 utf-8 字符,那么您是对的。

This is the kind of temporary arrangement I found for the moment (unicode->utf8?ascii?, listFolder is a std::string)

您在那里尝试做的是将一些 unicode 字符替换为具有平台定义编码的字符。如果除此之外还有其他 unicode 字符,那么您最终会得到一个具有混合编码的字符串。此外,在某些情况下,它可能会意外地替换其他字节序列的一部分。我建议使用库来转换编码或对编码字符串进行任何其他操作。