曲径通幽论坛

标题: setlocale() -- 设置当前 locale [打印本页]

作者: beyes    时间: 2011-6-14 18:22
标题: setlocale() -- 设置当前 locale
在 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 编码。看一下运行后输出什么:
[beyes@beyes   C]$ ./wchar
?
一个问号,表明系统无法识别这个编码。其原因正是和 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 。然后再运行该程序:
[beyes@beyes   C]$ ./wchar
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" 这种情况。




欢迎光临 曲径通幽论坛 (http://www.groad.net/bbs/) Powered by Discuz! X3.2