在 linux 系统中,如果要获得正确的当地语言显示,必须正确的设置 locale 。使用 locale 命令可以看到当前系统的 locale 设置值。
setlocale() 函数可以用来设置当前的 locale 。它声明如下:
[C++] 纯文本查看 复制代码 #include <locale.h>
char *setlocale(int category, const char *locale);
setlocale() 有两个参数,第一个参数是 category,它实际就是 locale 命令打印出来的各个设置项,如LC_COLLATE,LC_MESSAGES...等等。第 2 个参数 locale 是个字符串指针,它的值是 "zh_CN.UTF-8" ,或 “en_US.utf8” 等等这些特定的 locale 项。
顺便说一下,locale 的命名规则是:<语言>_<地区名>.<字符编码名称>
当 setlocale() 的第 1 个参数是 LC_ALL 而第 2 个参数为空时, 那么采用当前系统默认使用的 locale 设置,也就是 locale 命令看到的那些. 假如 locale 不为空,那么会将第 2 个参数中的 locale 值代替所有的 LC_* 项目。
下面以示例说明:
我现在在一个 locale 设置为 zh_CN.UTF-8 的中文 linux 上运行下面的代码:
[C++] 纯文本查看 复制代码 #include <wchar.h>
#include <locale.h>
int main(void)
{
wprintf (L"\u2593\n");
return 0;
}
在上面程序中,wprintf() 函数里使用了 L 这个符号,这是因为:为了在程序中操作 Unicode ,在 C 中定义了宽字符(wide character)类型 wchar _t 以及一些库函数,在字符常量或一个字符串前面加上一个 L 就表示声明了一个宽字符常量或宽字符字符串。比如 wchar_t c = L“你好" 。
这里 wprintf() 函数里的参数是扩展 ASCII 码(128-255 之后的编码)中的 "▓" 符号 Unicode 编码。看一下运行后输出什么:一个问号,表明系统无法识别这个编码。其原因正是和 locale 有关,在默认情况下,setlocale() 采用的是 LC_CTYPE 为 "C" 或 "POSIX" 这种设置,因为这具有较好的移植性。当 LC_CTYPE 为 "C" 或 "POSIX" 时,采用的正是 7 位的 ASCII 码,这个编码的标准范围是 0-127,而 128-255 之后为扩展码,所以这里是无法显示的。
那么修改一下上面的程序:
[C++] 纯文本查看 复制代码 #include <wchar.h>
#include <locale.h>
int main(void)
{
setlocale (LC_ALL, "en_US.utf8");
wprintf (L"\u2593\n");
return 0;
}
这里使用了 setlocale() 将所有的 LC_* 都设置为 en_US.utf8 。然后再运行该程序:OK,正确的显示出来了!这里编译程序时要注意添加 -std=c99 这个选项,不然会出现下面的警告: [beyes@beyes C]$ gcc wchar.c -o wchar
wchar.c: 在函数‘main’中:
wchar.c:8:11: 警告:Unicode 字符名只在 C++ 和 C99 中有效 [默认启用] 在上面程序中,如果使用 setlocale (LC_ALL, ""); 一样奏效,因为不管是 zh_CH.UTF-8 还是 en_US.utf8 它们同样都是 UTF-8,都能够解析这种以 Unicode 形式出现的字符。
同理,如果我们的系统原本就是英文的,但还是要用 setlocale() 来设置一下环境的,不然默认以 ASCII 码来输出得到的也是个 ? 号,如:
[C++] 纯文本查看 复制代码 #include <wchar.h>
#include <locale.h>
int main(void)
{
setlocale(LC_ALL, "");
wprintf (L"\u2593\n");
return (0);
}
注意上面环境中的 setlocale() 函数里的第 2 个参数为空,表明使用系统正在使用的 locale 的设置。如果不使用 setlocale() 设置,默认还是使用 LC_CTYPE 为 "C" 或 "POSIX" 这种情况。 |