C标准库的setlocale()用法笔记
转自:http://zyxhome.org/wp/cc-prog-lang/c-stdlib-setlocale-usage-note/
[在此向原文作者说声谢谢!若有读者看到文章转载时请写该转载地址,不要写我的BLOG地址。尊重他人的劳动成果 ^_^ ]
C 和 C++ 的标准库分别有自己的 locale 操作方法,C 标准库的 locale 设定函数是 setlocale(),而 C++ 标准库有 locale 类和流对象的 imbue() 方法。这篇是我自己的 setlocale() 使用总结。
Linux的glibc中的setlocale()
具体参考:man 3 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的CRT中的setlocale()
具体参考:setlocale - MSDN Run-Time Library Reference
在 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):
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
.code_page:可以直接使用代码页来设定 locale,而且可以使用 .OCP、.ACP 两个伪代码页,.OCP 表示从系统获得的当前活动的 OEM 代码页,.ACP 表示从系统获得的活动 ANSI 代码页。
"":根据 Windows 系统环境的活动 ANSI 代码页来设定 locale。.OCP、.ACP、和环境代码页都受控制面板中“区域与语言选项”的设置影响。默认装完简体中文版 Windows 后,活动的 ANSI 代码页为:936(即 GBK),可用 chcp 控制台程序查看活动代码页。
NULL:取回当前 locale,不改变当前 locale。
setlocale()的作用和使用例子
当向终端、控制台输出 wchar_t 类型的字符时,需要设置 setlocale(),因为通常终端、控制台环境自身是不支持 UCS 系列的字符集编码的,使用流操作函数时(如:printf()),在标准/RT库实现的内部会将 UCS 字符转换成合适的本地 ANSI 编码字符,转换的依据就是 setlocale() 设定的活动 locale,最后将结果字符序列传递给终端,对于来自终端的输入流这个过程刚好相反。
可以用重定向输出流到文件的方法验证上面的机制:无论是 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_GBK void print_current_loc(); int main(int argc, char* argv[]) { char* locname = NULL; const wchar_t* strzh = L"中文字符串"; print_current_loc(); // 使用指定的 locale locname = 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; } // 打印当前 locale void 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 时,要在终端显示正确的中文,需满足以下条件:
不要混用 char 和 wchar_t 版本的流操作函数,否则会导致这些函数运行异常,我用Cygwin GCC 4测试混用 printf() 和 wprintf() 时,程序甚至崩掉,所以要将上面程序中 printf() 语句全注释掉才行。Window CRT 的实现则没有这个问题。
运行环境的 locale 设置要和程序中 setlocale() 设定的 locale 一致,比如:终端的活动字符集、环境变量(一般用 LANG),要设置为 *.UTF-8,才能显示 setlocale(LC_ALL, "zh_CN.UTF-8") 设定的 wchar_t 的中文字符。
用 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。
用 wprintf() 时,要用 %ls 表示 wchar_t 的字符串,用 %s 表示 char 的字符串,具体参考:man 3 wprintf,而 Windows 的实现用 %ls、%s 都可以正确输出 wchar_t 字符串。
相关推荐
这里要注意两个函数的使用,用来获取当前的日期来知道星期几 1. 第一个setlocale(LC_TIME,"chs");setlocales:本地化环境;LC_TIME:用来设置本地环境的日期形式;"chs":简体中文; 2. 第二个函数也是变量:$...
setlocale(LC_ALL,"zh_CN.UTF-8");//设置本地编码格式 n=mbstowcs(wt,input,x);//将汉字转换成宽字符类型 sprintf(output+4*i,"X",wt[i]);//将宽字符型转换成十六进制 sscanf(ch+4*x,"X",wch+x);//将十六进制转换成...
windows:代码第二行前插入一行:setlocale(LC_ALL, 'C'); 本系统核心pdf处理代码基于fpdf,(MIT license)。 优于pdf证书仅部分电脑端浏览器支持预览,故仅查询和下载。 自带数据和图片仅供演示,请勿将本系统用于...
windows:代码第二行前插入一行:setlocale(LC_ALL, 'C'); 公布代码旨在提高各类证书信息化率,比如很多县乡培训机构证书难以查询。 使用: 需要替换自己背景图及坐标参数文件、数据及照片、修改代码文件里网站标题等...
定义和用法 localeconv()函数返回一个包含本地数字及货币格式信息的数组。 localeconv()函数返回以下数组元素: [decimal_point] – 小数点字符 [thousands_sep] – 千位分隔符 [int_curr_symbol] – 货币符号 ...
设置区域 用于设置设备区域设置的简单应用程序。 注意:在 Android 4.2 及更高版本上,您必须手动授予应用所需的权限: ...下午授予 com.darkrockstudios.apps.setlocale android.permission.CHANGE_CONFIGURATION
写了这么多VBS,从来都没有使用过SetLocale函数,似乎也没有见过谁的代码使用过,这个SetLocale函数到底有什么用呢
一是在您的程序中直接使用setlocale函数设置Windows的编码方式为中文(好像中文的值是.936); setlocale(LC_ALL,”chs”); 二是在CMake编译的时候就选择OSG_USE_UTF8_FILENAME选项,然后重新编译OSG 下面是个一个...
iso,国际标准光盘文件系统格式。符合ISO 9660标准的光盘镜像文件格式,文件扩展名通常为iso。这种文件可以简单的理解为复制光盘上全部信息而形成的镜像文件。ZIP,是一个文件的压缩的算法,原名Deflate(真空),...
[ ]( ) 信息 该图像用于将语言环境设置为en_US.UTF-8。 它用作其他项目的基础图像。 Docker建立在: 您将获得“成功构建” 但是,当您测试locale-gen en_US.UTF-8 ,它失败了[ ]( ) 当您尝试从Ubuntu映像...
Sys.setlocale("LC_TIME", "C") ## [1] "C"----------------------------------------------------------- ## Create a function,the parameter 'i' means page number. getdata (i){ url ("www.cnblogs.com/p",i)#...
/bin/bash:warning:setlocale:LC_ALL:cannot change locale (zh_CN.UTF-8) It was not possible to find any installed .NET Core SDKs Did you mean to run .NET Core SDK commands? Install a .NET Core SDK fr
但服务器上,很多使用Linux服务器,源程序使用UTF-8,这样很容易产生字符编码的问题. 如果仅仅将CSV文件转码为UTF-8,这样在Windows服务器上没有问题, 而在RedHat5.5上,用fgetcsv取得的数组中,如果某列的内容是中文,则该...
编程技术APS#包括<stdio>#包括<stdlib>#包括<locale>#包括#包括<conio>#包括<windows> 使用命名空间std; int main(){float x,y; int op; setlocale(LC_ALL,“”); SetConsoleTextAttribute...
22个常见的wordpress问题集合,所有的wordpress问题全部解答,没有解答不了的问题,只要不认真看的。
如果您希望手动创建而不是使用该库使用的约定,那么熟悉它会帮助您了解如何构建和操作翻译包。 设置当前语言环境 use Cake \ I18n \ I18n ; I18n :: setLocale ( 'en_US' ); 设置包含po文件的文件夹的路径。 use ...
此文件夹包含许多小型测试程序。 我的StackOverflow解决方案: setlocale.c chrono.cpp bash_read_line / do.sh express-curl-xml / flask_classy_demo / sinon_doh_demo / 材料: 向量 fifo队列
ZTokenizer ... setlocale(LC_ALL, "chs"); wstring str = L"永和服装饰品有限公司"; ZTokenizer zTokenizer(str, true); while (true) { auto result = zTokenizer.next(); if (result.length() >
The C Library Reference Guide by Eric Huss © Copyright 1997 Eric Huss Introduction 1. Language 1.1 Characters 1.1.1 Trigraph Characters 1.1.2 Escape Sequences 1.1.3 Comments 1.2 Identifiers ...
C程序 Programs desenvolvidos durante meus estudos na linguagem C(Alguns deles feitos da IDE CodeBlocks) 出现问题的编程程序,将apenas acrescente pt_BR entre作为aspas duplas em setlocale(LC_ALL, "") ...