2011-12-21 64 views
-4

这是一个关于Unicode的初学者问题。我正在使用Embarcadero C++ Builder 2009,他们据说改变了默认字符串以使用Unicode。Unicode转换问题

  • 我在我的源代码编辑器中输入了各种不符合标准“7位ASCII”的符号。
  • 我的程序使用C++ Builder的String类型来获取用户输入。
  • 我也通过将值设置为wchar_t来手动添加输入。

似乎在解释符号的方式上存在冲突。有时我会得到一个符号,例如代码0x00C7('Ç'),但有时候相同的符号会被编码为0xFFC7,例如在源代码编辑器中。据我了解,前者是合适的Unicode,后者是“别的东西”。有人能证实这一点吗?

我在想这个“别的东西”编码是从哪里来的,以及如何摆脱它?

编辑:进一步的研究:它似乎是0xFF的**出现编码,其中一个地方就是,当我做这样的事情:

string str = ...; 
wchar_t wch = (wchar_t)str[i]; 

同样的结果不管它是的std :: string或VCL字符串。 wchar_t与Unicode不一样吗?

+0

如果使用utf-8进行编码,则每个unicode字符可能占用1,2或4个字节或更多。据我了解,wchar_t每个字符的大小总是2个字节,所以可能是问题所在。 – greatwolf 2011-12-21 10:23:16

+0

@VictorT。那么我应该使用哪种字符类型?我认为普通** char **是8位。 – Lundin 2011-12-21 10:27:36

+0

对于宽字符的字符串(Unicode),您应该使用'wstring'而非'string'。新的'String'类型使用以UTF-16存储的宽字符(不要担心其他编码,例如UTF8)。你的代码'string str = ...;'会丢失数据。那么你不应该在你的第二行需要演员阵容。 – 2011-12-22 16:13:30

回答

4

我猜测问题是在你的编译器char被签名(标准允许它是有符号或无符号的,它是实现定义/特定的)。因此,无论何时将位7设置为1(0x80至0xFF)的字符转换为任何更大的整数类型,都将其视为负值,并将其标记扩展以保留负值,换句话说,第7位被复制到第8位,第9位等,并被分配到较大整数类型的所有较高位中。所以,0xC7可以变成0xFFC7和0xFFFFFFC7。为防止发生这种情况,请先将chars改为unsigned chars

+0

我也怀疑这一点,所以我小心地使用我自己的uint8类型的字符。但是,我猜** ** char **可能被某些字符串类型或库对象内部使用。 – Lundin 2011-12-21 10:56:50

+0

C++的'string'通常为每个字符串元素使用普通的'char'。如果'char'有符号,那么'str [some index]'也是如此,因此只要它在表达式(包括赋值)中使用,就会受到符号扩展的影响。 – 2011-12-21 11:00:25

+0

我刚刚意识到源代码中的char文字最可能是** char **类型,或者更确切地说,int被截断为char。他们的确会被解释为负数。这解释了一些古怪但不是全部。 – Lundin 2011-12-21 11:02:08

1

宽字符类型w_type是实现定义的,不需要对应于Unicode字符的概念。检查出description of w_type in the Unicode Standard

如果“Ç”更改为0xFFC7,它看起来非常像符号扩展名,即字符内部存储为字节0xC7,然后将其作为有符号的8位整数并转换为16位整数签名扩展。

+0

对wchar_t的签名是否有任何保证,是否总是未签名/签名?因为看起来wchar_t可能是这里的罪魁祸首。 – Lundin 2011-12-21 10:58:45

+2

'wchar_t'的签名并不是这里的罪魁祸首。罪魁祸首是'char'的签名。 – 2011-12-21 11:07:52

+0

@Alex不够好,但出于好奇,标准对wchar_t的签名有什么意义? – Lundin 2011-12-21 12:06:29