我写的是需要能够在所有语言文字工作的程序。 我的理解是UTF-8将做的工作,但我遇到了它的一些问题。
难道我说得对,UTF-8可以存储在一个简单的char
在C ++? 如果是这样,为什么会出现以下警告,当我使用一个程序, char
, string
和stringstream
: warning C4566: character represented by universal-character-name '\uFFFD' cannot be represented in the current code page (1252)
。 (当我使用我没有得到这个错误wchar_t
, wstring
和wstringstream
。)
此外,我知道,UTF是可变长度。 当我使用at
或substr
字符串方法我会得到错误的答案?
要使用UTF-8字符串文字,你需要使用的前缀他们u8
,否则你会得到实现的字符集(在你的情况,这似乎是Windows的1252): u8"\uFFFD"
与字节的空值终止序列UTF-8的替换字符(U + FFFD)的表示。 它已键入char const[4]
由于UTF-8变长,各种索引会做代码单元,而不是代码点的索引。 这是不可能做到在UTF-8序列码点上的随机访问,因为它的长度可变的性质。 如果你想随机访问,你需要使用固定长度编码,像UTF-32。 对于您可以使用U
对字符串的前缀。
是的,UTF-8编码可以与字符,字符串和字符串流被使用。 一个char将保持单个UTF-8代码单元,其中多达四个可能被要求来表示单个Unicode代码点。
不过,也有使用UTF-8特别是与微软的编译器的几个问题。 C ++实现使用一个“执行字符集”的一些事情,诸如编码字符和字符串。 VC ++始终使用系统区域设置编码为执行字符集,和Windows不支持UTF-8作为系统的locale编码,因此UTF-8也不能依照执行字符集。
这意味着VC ++从未故意产生UTF-8字符和字符串。 相反,编译器必须被欺骗。
编译器将来自已知源码编码到执行编码转换。 这意味着,如果编译器使用的语言环境编码源和执行二者的编码则没有转换完成。 如果你能得到UTF-8的数据到源代码,但让编译器认为源使用区域设置编码,然后字符和字符串将采用UTF-8编码。 VC ++使用所谓的“BOM”检测源编码,并且如果没有检测到BOM使用地区编码。 因此,您可以通过保存您的所有源文件“UTF-8无签名”获得UTF-8编码字符串文字。
有使用这种方法的注意事项。 首先,你不能用窄字符和字符串使用UCNs。 通用字符名必须被转换到执行字符集,这是不UTF-8。 您必须字面上写的字,因此为UTF-8在源代码中出现,也可以采用十六进制转义,可以手动写了一个UTF-8编码。 第二,以产生宽字符和字符串的编译器执行从所述源编码到广角执行字符集类似的转换(这始终是UTF-16在VC)。 由于我们说谎有关的编码,编译器,它会不正确地执行这种转换为UTF-16。 因此,在宽字符和字符串,你不能随便使用非ASCII字符,而是必须使用UCNs或十六进制转义。
UTF-8是可变长度(如为UTF-16)。 与所使用的索引at()
和substr()
是代码单元而不是字符或代码点索引。 所以,如果你想有一个特殊的代码单元,然后你可以字符串索引或数组或无论是正常的。 如果需要一个特定的代码点则要么需要,可以理解构成UTF-8代码单元到代码点(如升压库的Unicode迭代器库 ),或者需要为UTF-8数据转换成UTF-32。 如果您需要实际用户感知的角色,那么你需要一个理解的代码点是如何组合成字符库。 我想象ICU具有这样的功能,或者你可以实现的默认字形簇边界规格从Unicode标准。
UTF-8的上述只考虑真正的问题你如何在源代码中写Unicode数据。 这对程序的输入和输出没有什么影响。
如果您的需求,您可以选择如何做输入和输出的话,我还是会建议使用UTF-8进行输入。 根据您需要输入该怎么做,你可以将它转换为另一种编码,很容易为你处理,或者你可以写你的处理程序直接在UTF-8中运行。
如果你想通过Windows控制台输出过任何东西,那么你会想要,可以有不同的实现方式输出一个定义良好的模块,因为国际化输出到Windows控制台将需要不同的实现从任一输出到一个文件在Windows或控制台而在其他平台上的文件输出。 (在其他平台上的控制台仅仅是另一个文件,但在Windows控制台需要特殊处理。)
您收到有关该警告的原因\uFFFD
是,你试图将FF FD
一个字节内,因为,正如你提到的,UTF-8的作品对char
S和可变长度。
如果您使用at
或substr
,你可能会得到错误的答案,因为这些方法算一个字节应该是一个字符。 这不是UTF-8的情况。 值得注意的是,同at
,你可以结束了一个字符序列的单字节; 与substr
,你可以打破一个序列,并与一个无效的UTF-8字符串(这将开始或结尾,结束了\uFFFD
,同一个你显然是想用了,破碎的字符将丢失)。
我会建议你使用wchar
来存储Unicode字符串。 由于类型为至少16位,许多许多字符可以适合在一个单一“单元”。