这是一个ANSI C的问题.我有以下代码
#include <stdio.h> #include <locale.h> #include <wchar.h> int main() { if (!setlocale(LC_CTYPE,"")) { printf( "Can't set the specified locale! " "Check LANG,LC_CTYPE,LC_ALL.\n"); return -1; } wint_t c; while((c=getwc(stdin))!=WEOF) { printf("%lc",c); } return 0; }
我需要完整的UTF-8支持,但即使在这个最简单的级别,我可以改进这个吗?为什么使用wint_t,而不是wchar,有适当的更改?
解决方法
UTF-8是Unicode的一种可能的编码方式.它定义每个字符1个,2个,3个或4个字节.当您读取它通过
getwc()
,它将获取一到四个字节,并从它们组成一个单一的Unicode字符代码点,这将适合一个wchar(根据平台可能是16或甚至32位宽).
但是由于Unicode值映射到从0x0000到0xFFFF的所有值,所以没有返回条件或错误代码的值(有些已经指出Unicode大于16位,这是正确的;在这些情况下,surrogate pairs是但是这里的意思是Unicode使用所有可用的值,而不是EOF.)
各种错误代码包括映射到-1的EOF(WEOF).如果要将getwc()的返回值放在wchar中,那么将无法区分它与Unicode 0xFFFF字符(其中,BTW,无论如何都保留,但我离题).
所以答案是使用一个更宽的类型,一个保持至少32位的wint_t(或int).这给出了实际值的低16位,任何设置在该范围之外的任何东西都意味着除了字符返回之外的东西.
为什么我们不总是使用wchar而不是wint?大多数与字符串相关的函数使用wchar,因为在大多数平台上,它的大小是wint的一半,因此字符串的内存占用空间更小.