如何让STL std :: string在Windows上使用unicode?

NSA*_*NSA 9 c++ windows string unicode stl

在我的公司,我们有一个跨平台(Linux和Windows)库,它包含我们自己的STL std :: string扩展,这个类在字符串之上提供所有类型的功能; 最近我们被要求使这个字符串unicode"友好"基本上它需要支持中文,日文,阿拉伯文等字符.经过初步研究,这在Linux方面似乎很好因为每件事本身就是UTF-8,但是我在Windows方面遇到了麻烦; 是否有一个技巧让STL std :: string在Windows上作为UTF-8工作?它甚至可能吗?有没有更好的办法?理想情况下,我们会基于std :: string保留自己,因为这是Linux中基于字符串类的内容.

谢谢,

Tho*_*mas 12

你的问题有几个误解.

  • C++和STL都没有处理编码.

  • std::string本质上是一个字节串,而不是字符.所以你应该没有问题填充UTF-8编码的Unicode.但是,请记住,所有string函数也适用于字节,因此myString.length()将为您提供字节数,而不是字符数.

  • Linux本身并不是 UTF-8.现在大多数发行版默认为UTF-8,但不应该依赖它.

  • 但是语言环境的名称可以包含编码的名称,例如en_US-UTF8,因此我说"STL不知道关于编码的_anything_"似乎是错误的. (2认同)

Tha*_*tos 9

是的 - 通过更多地了解区域设置和编码.

Windows有两个函数调用,用于需要文本的所有内容,一个FoobarA()和一个FoobarW().*W()函数采用UTF-16编码的字符串,*A()采用当前代码页中的字符串.但是,Windows不支持UTF-8代码页,因此您无法使用*A()函数直接使用它,也不希望依赖于用户设置的代码页.如果在Windows中需要"Unicode",请使用支持Unicode的(*W)函数.有教程,谷歌搜索"Unicode Windows教程"应该会给你一些.

如果要将UTF-8数据存储在std :: string中,那么在将其传递给Windows之前,请将其转换为UTF-16(Windows提供执行此操作的功能),然后将其传递给Windows.

许多这些问题源于C/C++通常与编码无关.char它不是一个真正的角色,它只是一个整体类型.char如果您需要访问单个代码单元,即使使用数组存储UTF-8数据也会让您遇到麻烦,因为char标准未定义签名.像str[x] < 0x80检查多字节字符的语句可以快速引入错误.(如果char签名,则该语句始终为true .)UTF-8代码单元是无符号整数类型,范围为0-255.这完全映射到C类型uint8_t,虽然unsigned char也可以.理想情况下,我将UTF-8字符串作为uint8_ts 的数组,但由于旧的API,很少这样做.

有些人推荐wchar_t,声称它是"Unicode字符类型"或类似的东西.同样,这里的标准与以前一样不可知,因为C意味着可以在任何地方工作,而且任何地方都可能没有使用Unicode.因此,wchar_t不再是Unicode char.标准规定:

这是一个整数类型,其值范围可以表示支持的语言环境中指定的最大扩展字符集的所有成员的不同代码

在Linux中,a wchat_t表示UTF-32代码单元/代码点.因此它是4个字节.但是,在Windows中,它是一个UTF-16代码单元,只有2个字节.(其中,我会说不符合上述规定,因为2字节不能代表所有Unicode,但这就是它的工作方式.)这种大小差异和数据编码的差异显然会给可移植性带来压力.wchar_t如果您需要可移植性,Unicode标准本身会建议您使用.(第5.2节)

最后一课:我发现将所有数据存储在一些声明良好的格式中是最容易的.(通常是UTF-8,通常在std :: string中,但我真的更喜欢更好的东西.)这里重要的不是UTF-8部分,而是我知道我的字符串是UTF-8.如果我将它们传递给其他API,我还必须知道该API需要UTF-8字符串.如果没有,那么我必须转换它们.(因此,如果我说Window的API,我必须首先将字符串转换为UTF-16.)UTF-8文本字符串是"橙色","latin1"文本字符串是"apple".一个char不知道它是什么编码的数组是一个灾难的秘诀.


Jer*_*fin 7

std::string无论平台如何,将UTF-8代码点放入一个应该没问题.Windows上的问题是几乎没有其他任何期望或与UTF-8一起工作 - 它期望并与UTF-16一起使用.您可以切换到std::wstring存储UTF-16(至少在大多数Windows编译器上),或者您可以编写其他接受UTF-8的例程(可能转换为UTF-16,然后传递给操作系统).

  • @NSA,您必须选择包含您要显示的字符的字体.很少有字体覆盖了很大一部分Unicode代码点. (3认同)
  • @NSA:这取决于.如果你尝试使用`cout`或`wcout`,那几乎就是一场灾难.如果将`wstring`的内容直接传递给Windows函数,事情就会简单得多(`printf`,这样的工作也很好).从那里开始,主要是确保您使用的字体可以显示您关心的所有字符. (2认同)

Mar*_*k B 5

你看过吗std::wstringstd::basic_string它是forwchar_t而不是charusing的版本std::string