一、C 和 C++ 的标准库分别有自己的 locale 操作方法,C 标准库的 locale 设定函数是 setlocale(),而 C++ 标准库有 locale 类和流对象的 imbue() 方法。这篇讲解 C 标准库中 setlocale() 的使用。

GNU libc 中的 setlocale():

头文件与声明如下:

  1. #include <locale.h>

  2. char* setlocale(int category, const char* locale);

说明

category:为locale分类,表达一种locale的领域方面,通常有下面这些预定义常量:LC_ALL、LC_COLLATE、LC_CTYPE、LC_MESSAGES、LC_MONETARY、LC_NUMERIC、LC_TIME,其中 LC_ALL 表示所有其它locale分类的并集。

locale:为期望设定的locale名称字符串,在Linux/Unix环境下,通常以下面格式表示locale名称:language[_territory][.codeset][@modifier],language 为 ISO 639 中规定的语言代码,territory 为 ISO 3166 中规定的国家/地区代码,codeset 为字符集名称。

在Linux下,可以使用 locale -a 命令查看系统中所有已配置的 locale。用不带选项的 locale 命令查看当前 Shell 中活动的 locale。用 locale -m 命令查看locale系统支持的所有可用的字符集编码。

和locale相关的包叫做:locales,locale系统支持的所有可用locale在文件:/usr/share/i18n/SUPPORTED 中列出。

在Debian下,可用 dpkg-reconfigure locales 命令重新配置 locale,也可以手工修改/etc/locale.gen 文件,然后运行 locale-gen 命令。

在Ubuntu下,修改 /var/lib/locales/supported.d/local 文件,配置新的 locale,然后运行 locale-gen 命令。

当 locale 为 NULL 时,函数只做取回当前 locale 操作,通过返回值传出,并不改变当前 locale。

当 locale 为 "" 时,根据环境的设置来设定 locale,检测顺序是:环境变量 LC_ALL,每个单独的locale分类LC_*,最后是 LANG 变量。为了使程序可以根据环境来改变活动 locale,一般都在程序的初始化阶段加入下面代码:setlocale(LC_ALL, "")。

当C语言程序初始化时(刚进入到 main() 时),locale 被初始化为默认的 C locale,其采用的字符编码是所有本地 ANSI 字符集编码的公共部分,是用来书写C语言源程序的最小字符集(所以才起locale名叫:C)。

当用 setlocale() 设置活动 locale 时,如果成功,会返回当前活动 locale 的全名称;如果失败,会返回 NULL。

二、Windows/VC CRT 的 setlocale()

参考 MSDN VC8, Run-Time Library Reference:

setlocale():设置 locale

_get_current_locale():返回当前的 _locale_t 值。

在 Windows CRT 的实现中还有一个使用 wchar_t 作为 locale 名的宽字符版本:_wsetlocale()。因此,也有了使用 _TCHAR 宏版本的 setlocale():_tsetlocale()

Windows CRT 实现的 setlocale() 和 glibc 版本的头文件与声明相同,使用方法类似,如下:

支持的 locale 分类常量:LC_ALL、LC_COLLATE、LC_CTYPE、LC_MONETARY、LC_NUMERIC、LC_TIME。

请求设定的 locale 名可以为以下格式(参考MSDN:Language and Country/Region Strings):

  1. lang[_country_region[.code_page]]:虽然形式与 glibc 的相同,当 Windows 的 locale 名并不符合 POSIX 的规范,比如采用 GBK 字符集的大陆中文,POSIX 的名字为:zh_CN.GBK,而在 Windows CRT 中要用:Chinese_People's Republic of China.936,(-_-^)。

    • lang 字段的可用值参考:Language Strings

    • country_region 字段的可用值参考:Country/Region Strings

    • code_page 字段的可用值是 Windows 系统支持的代码页编号,参考:Code Page Identifiers

  2. .code_page:可以直接使用代码页来设定 locale,而且可以使用 .OCP、.ACP 两个伪代码页,.OCP 表示从系统获得的当前活动的 OEM 代码页,.ACP 表示从系统获得的活动 ANSI 代码页。

  3. "":根据 Windows 系统环境的活动 ANSI 代码页来设定 locale。.OCP、.ACP、和环境代码页都受控制面板中“区域与语言选项”的设置影响。默认装完简体中文版 Windows 后,活动的 ANSI 代码页为:936(即 GBK),可用 chcp 控制台程序查看活动代码页。

  4. NULL:取回当前 locale,不改变当前 locale。

三、setlocale() 的作用和使用示例

当向终端、控制台输出 wchar_t 类型的字符时,需要设置 setlocale(),因为通常终端、控制台环境自身是不支持 UCS 系列的字符集编码的当我们使用流操作函数时(如:printf()/fopen_s等),在标准/RT库实现的内部会将 UCS 字符转换成合适的本地 ANSI 编码字符,转换的依据就是 setlocale() 设定的活动 locale,最后将结果字符序列传递给终端,对于来自终端的输入流这个过程刚好相反。所以,当我们使用流操作函数之前,往往需要使用setlocale函数实现字符集编码转换

可以用重定向输出流到文件的方法验证上面的机制:无论是 Windows CRT、Linux glibc、Cygwin glibc,使用 wprintf() 打印 wchar_t 字符文本时,重定向到文件的内容总是 GBK、UTF-8 等本地 ANSI 编码,而不会是 UCS 编码。

下面是我写的一个使用 setlocale() 的示例:

#ifdef __GNUC__#define CSET_GBK "GBK"#define CSET_UTF8 "UTF-8"#define LC_NAME_zh_CN "zh_CN"// ifdef __GNUC__#elif defined(_MSC_VER)#define CSET_GBK "936"#define CSET_UTF8 "65001"#define LC_NAME_zh_CN "Chinese_People's Republic of China"// ifdef _MSC_VER#endif#define LC_NAME_zh_CN_GBK LC_NAME_zh_CN "." CSET_GBK#define LC_NAME_zh_CN_UTF8 LC_NAME_zh_CN "." CSET_UTF8#define LC_NAME_zh_CN_DEFAULT LC_NAME_zh_CN_GBKvoid print_current_loc();int main(int argc, char* argv[]){char* locname = NULL;const wchar_t* strzh = L"中文字符串";print_current_loc();// 使用指定的 localelocname = setlocale(LC_ALL, LC_NAME_zh_CN_DEFAULT);if ( NULL == locname ){printf("setlocale() with %s failed./n", LC_NAME_zh_CN_DEFAULT);}else{printf("setlocale() with %s succeed./n", LC_NAME_zh_CN_DEFAULT);}print_current_loc();wprintf(L"Zhong text is: %ls/n", strzh);// 使用运行环境中的 locale 设置locname = setlocale(LC_ALL, "");if ( NULL == locname ){printf("setlocale() from environment failed./n");}else{printf("setlocale() from environment succeed./n");}print_current_loc();wprintf(L"Zhong text is: %ls/n", strzh);puts("End of program.");return 0;}// 打印当前 localevoid print_current_loc(){char* locname = setlocale(LC_ALL, NULL);printf("Current locale is: %s/n", locname);}

四、要使上面程序成功编译并执行,需要注意一下几点:

Windows CRT 是不支持 UTF-8 编码作为 locale 的,运行时使用 setlocale(LC_ALL, ".65001") 会失败。

使用 Linux 和 Cygwin 的 glibc 时,要在终端显示正确的中文,需满足以下条件:

  1. 不要混用 char 和 wchar_t 版本的流操作函数,否则会导致这些函数运行异常,我用Cygwin GCC 4测试混用 printf() 和 wprintf() 时,程序甚至崩掉,所以要将上面程序中 printf() 语句全注释掉才行。Window CRT 的实现则没有这个问题。

  2. 运行环境的 locale 设置要和程序中 setlocale() 设定的 locale 一致,比如:终端的活动字符集、环境变量(一般用 LANG),要设置为 *.UTF-8,才能显示 setlocale(LC_ALL, "zh_CN.UTF-8") 设定的 wchar_t 的中文字符。

  3. 用 GCC 编译时,要使用 UTF-8 编码保存源文件,这是 GCC 在编译时,将 wchar_t 文字量(以 L 打头)正确转换为 UCS 编码保存在对象文件中的必需条件,用 Native ANSI 编码(比如:GBK)有 wchar_t 文字量的源文件时,GCC 会编译出错,Linux 和 Cygwin 的 GCC 都有这个约束。另外在 Linux GCC 使用 UCS-4 编码保存 wchar_t,而 Windows 和 Cygwin GCC 使用 UCS-2。

  4. 用 wprintf() 时,要用 %ls 表示 wchar_t 的字符串,用 %s 表示 char 的字符串,具体参考:man 3 wprintf,而 Windows 的实现用 %ls、%s 都可以正确输出 wchar_t 字符串。

这里有一篇 Love Katherine 的:浅谈 C 中的 wprintf 和宽字符显示,是对 Linux 使用 wchar_t 的分析。

setlocale()函数的作用相关推荐

  1. python函数的作用是_Python函数一

    函数 一.函数的作用 函数就是一段具有独立功能的代码块整合到一个整体并命名,在需要的位置调用这个名称即可完成对应的需求 函数在开发过程中,可以更高效的实现代码重用 二,函数的使用步骤 2.1 定义函数 ...

  2. python中匿名函数的作用_Python 中的匿名函数,你会用吗

    原标题:Python 中的匿名函数,你会用吗 概念 我们从一个例子引入. 这里有一个元素为非空字符串的列表,按字符串最后一个字母将列表进行排序.如果原列表是 ['abc', 'g', 'def'],则 ...

  3. java中的string函数_java中string.trim()函数的作用实例及源码

    trim()的作用:去掉字符串首尾的空格. public static void main(String arg[]){ String a=" hello world "; Str ...

  4. Win32 API之Setlocale函数配置地域化信息函数

    setlocale: 函数原形为:char *setlocale( int category, const char *locale ); 头文件:<locale.h> 所支持的操作系统为 ...

  5. VC++ inline内联函数的作用解决方案

    VC++ inline内联函数的作用解决方案 __attribute__((always_inline)) attribute((always_inline))的意思是强制内联,所有加了attribu ...

  6. C语言中内联函数的作用 inline

    C语言中内联函数的作用 inline C语言中内联函数到底有什么作用? 试想一下,每当我们在假设就在主函数中调用另外一个函数的时候,那么这个函数就要入栈或者出栈,比如说下面的一个例子: 点击(此处)折 ...

  7. python主函数的作用_python中main函数的用法

    原博文 2020-03-27 20:25 − **什么场景下会有main函数?** 当该python脚本被作为模块(module)引入(import)时,其中的main()函数将不会被执行. **ma ...

  8. 【Android 逆向】ptrace 函数 ( C 标准库 ptrace 函数简介 | ptrace 函数真实作用 )

    文章目录 一.C 标准库 ptrace 函数简介 二.ptrace 函数真实作用 一.C 标准库 ptrace 函数简介 ptrace 函数 : 在 C 标准库 中有一个 ptrace 函数 , 该函 ...

  9. STM32中NVIC_SystemReset()函数的作用?什么时候用?

    STM32中NVIC_SystemReset()函数的作用?什么时候用? STM32软件复位有两种方式 (1)方式一:NVIC_SystemReset()函数用来复位STM32. 注意1:从SYSRE ...

  10. Softmax 函数及其作用(含推导)

    Softmax函数的定义及作用 Softmax是一种形如下式的函数: P(i)=exp(θTix)∑Kk=1exp(θTkx) 其中 θi和x是列向量, θTix可能被换成函数关于x的函数 fi(x) ...

最新文章

  1. 11.3-全栈Java笔记:线程的生命周期
  2. 空间简史-人类认识空间的旅程与其对强化学习的启示
  3. linux 命令行简介
  4. libqrencode生成二维码图片的问题
  5. Oracle计算时间差函数
  6. NTU 课程笔记:MAS 714(16) 图灵机
  7. 大数据之mongodb -- (2)java集成 MongoDB 3.2,使用Spring-data-mongodb进行集成
  8. 转载:SVN插件的手动安装
  9. 多线程面试题之原子性、可见性、有序性
  10. LDAPimplementation
  11. CodeForces 444C. DZY Loves Physics(枚举+水题)
  12. WAREZ无形帝国(盗版之源)
  13. Windows-caffe安装
  14. tplink怎么进去_在TP-Link工作体验如何?
  15. android espresso跨程序,Android中使用Espresso进行UI测试
  16. ESXI安装OpenWRT LEDE软路由部署指南(附镜像下载)
  17. 使用Python中的Button组件制作按钮
  18. CISCO APIC-M2无法安装APIC软件故障解决
  19. React Native常用第三方组件汇总【建议收藏】
  20. java环境变量设置.

热门文章

  1. 腾讯word2vec模型缩小版
  2. 青少儿编程Python入门教程——Python基础知识库
  3. git项目文件上不显示图标的问题(绿色,红色)
  4. 【插值】插值方法原理详解
  5. 世界首富马斯克的编程水平怎么样?
  6. php 批量导入表格,织梦dedecms批量导入excel表文章内容插件
  7. 英语读音(四)--自然拼读法 Phonics --- 最常见字母发音 /The pronounciation of most common letters
  8. python 频谱图_SciPy spectrogram:计算频谱图
  9. C盘清理攻略--拯救你的C盘空间
  10. 小夜灯离线语音识别芯片IC 声控小夜灯IC