在C11和C++ 11中转换UTF-8的标准方式?

Bri*_*ell 18 unicode utf-8 character-encoding c++11 c11

C11和C++ 11都引入了uchar.h/ cucharheader定义char16_tchar32_t明确的16和32位宽字符,添加了文字语法,u""U""用于编写具有这些字符类型的字符串,以及宏,__STDC_UTF_16____STDC_UTF_32__告诉您它们是否对应于UTF-16和UTF-32代码单元.这有助于消除wchar_t在一些平台上16位且通常用于保存UTF-16代码单元的模糊性,并且在某些平台上是32位并且通常用于保存UTF-32代码单元; 假设现在设置了这些宏,您现在可以编写引用UTF-16和UTF-32的可移植,明确的代码.__STDC_ISO_10646__也可以用作代理来确定是否wchar_t能够保持UTF-32值; 如果它不能,你不一定会认为它拥有UTF-16,但它可能是一个足够近似的便携式.

他们还增加了功能mbrtoc16,mbrtoc32,c16rtomb,并c32rtomb为多字节字符和这些类型之间的转换.在这些和现有mbstowcs的函数系列之间,可以在UTF-16,UTF-32,平台多字节字符集和平台宽字符集之间进行可移植的转换(尽管不一定是无损的,除非平台定义了多字节和宽字符集是UTF;特别是,似乎这些函数在Windows上相当无用,其中语言环境定义的多字节编码不允许每个字符使用两个以上的字节).

此外,他们还添加了u8""编写文字UTF-8编码字符串的语法.由于UTF-8的编码是与经营的大部分功能兼容char *std::string,这是最有用的新增加的一个.

但是,它们似乎未能添加任何方式来在UTF-8,UTF-16和UTF-32之间进行可移植转换.的mbtoc16实现中定义多字节编码和UTF-16或32之间,并且相关的功能转换; 但你不能依赖这是UTF-8.在类Unix的平台上,它依赖于语言环境,并且其中许多默认情况下在其语言环境中使用UTF-8,即使它不是默认语言,您至少可以将语言环境设置为UTF-8语言环境以便知道"多字节"表示UTF-8.但是,在Windows上,您明确不能使用UTF-8或任何其他需要超过两个字节的编码.

我只是遗漏了一些东西,或者是UTF-8字符串类型没有任何方式将其转换为其他类型的字符串:平台定义的多字节,平台定义的宽字符,UTF-16或UTF-32?甚至无法判断您的系统多字节编码是否为UTF-8?是否有任何理由不包括这种支持(具体来说,我正在寻找C或C++标准委员会的实际书面理由或讨论,而不仅仅是猜测)?是否有任何工作要改善这种情况; 是否有可能在未来改善?

或者,是目前最好的解决办法,如果你想支持UTF-8在便携时尚,写自己的实现,拉库的依赖,或使用特定于平台的功能,如iconvMultiByteToWideChar

Mik*_*keP 0

听起来您正在寻找std::codecvt类型。请参阅该页面上的示例以了解用法。

  • 啊,这回答了 C++11 的问题。我对C11还是很好奇。我可能会将我的问题更新为仅关于 C11,但由于 Microsoft 明确拒绝支持 C89 之外的任何内容,因此询问有关 Windows 的可移植性的问题可能是徒劳的。有趣的是,正如您在该页面底部的图表中看到的那样,对于某些转换,您可以使用“std::codecvt”,对于某些转换,您必须使用 C 样式转换函数,而有些转换则不需要。尽管您可以通过其他组合来组合它们,但它们并不直接存在。 (2认同)
  • 另请注意,标准 codecvts 仅提供 UTF-8 和 UTF-16、UCS-2 或 UTF-32 之间的转换,而不提供 UTF-8 和平台字符集之间的转换。为此,您需要使用“c32rtomb”之类的工具进行两次转换。 (2认同)