我一直在阅读有关 Unicode 主题的一些资料——特别是 UTF-8——C++11 中的(非)支持,我希望 Stack Overflow 上的专家可以让我放心,我的理解是正确的,或者指出我误解或遗漏的地方,如果是这样的话。
一个简短的总结
首先,好处是:您可以在源代码中定义 UTF-8、UTF-16 和 UCS-4 文字。另外,<locale>
header 包含多个 std::codecvt
可以在任何 UTF-8、UTF-16、UCS-4 和平台多字节编码之间转换的实现(尽管 API 似乎,委婉地说,不太简单)。这些 codecvt
实现可以是 imbue()
'd 在流上允许您在读取或写入文件(或其他流)时进行转换。
[ 编辑: Cubbi 在评论中指出我忽略提及 <codecvt>
header ,提供 std::codecvt
不依赖于语言环境的实现。另外,std::wstring_convert
和 wbuffer_convert
函数可以使用这些codecvt
s 直接转换字符串和缓冲区,而不依赖于流。]
C++11 还包括 C99/C11 <uchar.h>
头文件包含将平台多字节编码(可能是也可能不是 UTF-8)中的单个字符转换为 UCS-2 和 UCS-4 的函数。
然而,这就是它的程度。虽然您当然可以将 UTF-8 文本存储在 std::string
中,我看不出有什么方法可以用它做任何真正有用的事情。例如,除了在代码中定义文字外,您无法验证字节数组是否包含有效的 UTF-8,您无法找出长度(即 Unicode 字符的数量,对于某些“字符”的定义) ) 的包含 UTF-8 的 std::string
,并且您不能迭代 std::string
以逐字节以外的任何方式。
同样,即使是 C++11 添加的 std::u16string
并不真正支持 UTF-16,而只支持较旧的 UCS-2——它不支持代理对,只剩下 BMP。
观察
鉴于 UTF-8 是几乎所有 Unix 派生系统(包括 Mac OS X 和* Linux)上处理 Unicode 的标准方式,并且在很大程度上已成为网络上的事实上的标准,现代 C++ 似乎缺乏支持就像一个非常严重的遗漏。即使在 Windows 上,事实是新的 std::u16string
不真正支持UTF-16似乎有些遗憾。
* 正如评论中指出并明确指出的here ,Mac OS 的 BSD 派生部分使用 UTF-8,而 Cocoa 使用 UTF-16。
问题
如果你能读完所有这些,谢谢!只是几个简单的问题,毕竟这是堆栈溢出......
编辑:谢谢大家的回复。我必须承认,我觉得他们有点令人沮丧——看起来现状在不久的将来不太可能改变。如果行家之间达成共识,那么完整的 Unicode 支持似乎太难了,任何解决方案都必须重新实现 ICU 的大部分才能被认为有用。
我个人不同意这一点。我认为可以找到有值(value)的中间立场。例如,UTF-8 和 UTF-16 的验证和规范化算法由 Unicode 联盟明确指定,并且可以由标准库作为免费函数提供,例如
std::unicode
命名空间。对于需要与需要 Unicode 输入的库进行交互的 C++ 程序,仅这些将是一个很大的帮助。但是根据下面的答案(必须说,带有一丝苦涩)似乎 Puppy 提出的这种有限功能的建议并没有得到很好的接受。
最佳答案
Is the above analysis correct
让我们来看看。
you can't validate an array of bytes as containing valid UTF-8
不正确。
std::codecvt_utf8<char32_t>::length(start, end, max_lenght)
返回数组中的有效字节数。you can't find out the length
部分正确。可以转换为 char32_t 并找出结果的长度。在不进行实际转换的情况下,没有简单的方法可以找出长度(但见下文)。我必须说,需要计算字符(在任何意义上)的情况很少出现。
you can't iterate over a std::string in any way other than byte-by-byte
不正确。
std::codecvt_utf8<char32_t>::length(start, end, 1)
使您可以遍历 UTF-8“字符”(Unicode 代码单元),当然还可以确定它们的数量(这不是计算字符数的“简单”方法,但它是一种方法)。doesn't really support UTF-16
不正确。可以使用例如在 UTF-16 和 UTF-16 之间进行转换。
std::codecvt_utf8_utf16<char16_t>
.转换为 UTF-16 的结果就是 UTF-16。它不限于 BMP。Demo that illustrates these points .
如果我错过了其他一些“你不能”,请指出,我会解决它。
重要附录 .这些设施是已弃用 在 C++17 中。这可能意味着它们将在 future 的 C++ 版本中消失。使用它们需要您自担风险。原始问题中列举的所有这些事情现在不能(安全地)再次完成,仅使用标准库。
关于c++ - C++11 中的 Unicode,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25249498/