【字符集四】c语言标准库<locale.h>

char * setlocale(int category, const char *locale);//我们主要讲解下和函数setlocale相关的知识点,侧重字符编码。

一、locale.h简介

  • C语言是世界性的编程语言,它支持全球的语言系统,可以处理英文、中文、日文、韩文、德语、法语、拉丁文、希腊文等。我们可以通过 <locale.h> 头文件中的 setlocale() 函数进行地域设置,改变程序的语言环境。

  • 地域设置是与某个地区(或者说某个国家)的语言和文化相关的一系列内容,包含字符集(字符编码)、日期格式、数字格式、货币格式(例如货币符号、国际货币代码)、字符处理(例如字符分类)、字符比较(字符排序)等。

  • 其中,数字和货币信息还包含了很多细节,为了便于管理,C语言将这些细节信息组织成一个名为 lconv 结构体。

区域设置会影响标准库中部分函数的行为,我们将在 setlocale() 中具体讲解。

  • locale.h介绍中我们可以看到,其<locale.h>一共提供了2个函数。简单来说,setlocale()是设置locale,二localeconv()是获取当前locale.如图
    在这里插入图片描述

参见:
1.locale.h
2.<locale.h>头文件详解

二、setlocale()简介

贴下locale.h中的对setlocale的介绍。

Sets locale information to be used by the current program, either changing the entire locale or portions of it. The function can also be used to retrieve the current locale’s name by passing NULL as the value for argument locale.
简单翻译:setlocale是用来设置当前程序的locale,当然,如果你把参数设置成NULL,会返回当前程序的locale。

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

1、setlocale的返回值

  • 返回一个char类型的指针,

char* lc = setlocale(LC_ALL , “.936”);

  • 成功:

返回一个指向字符串的指针,该字符串包含了当前地域设置的名称
If a valid locale and category are given, returns a pointer to the string associated with the specified locale and category.

  • 失败:

lc为NULL

参见:
1.setlocale, _wsetlocale

2、setlocale的参数

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

2.1、第一个参数:int category

  • 地域设置的影响范围。地域设置包含日期格式、数字格式、货币格式、字符处理、字符比较等多个方面的内容,当前的地域设置可以只影响某一方面的内容,也可以影响所有的内容,通过 category 参数就可以指明地域设置的影响范围。
  • category 的值不能随便设置,必须使用 <locale.h> 中定义的宏,下表列出了宏名及其说明。
项目Value
LC_ALLAll categories, as listed below.
LC_COLLATEThe strcoll, _stricoll, wcscoll, _wcsicoll, strxfrm, _strncoll, _strnicoll, _wcsncoll, _wcsnicoll, and wcsxfrm functions.
LC_CTYPEThe character-handling functions (except isdigit, isxdigit, mbstowcs, and mbtowc, which are unaffected).
LC_MONETARYMonetary-formatting information returned by the localeconv function.
LC_NUMERICDecimal-point character for the formatted output routines (such as printf), for the data-conversion routines, and for the non-monetary formatting information returned by localeconv. In addition to the decimal-point character, LC_NUMERIC sets the thousands separator and the grouping control string returned by localeconv.
LC_TIMEThe strftime and wcsftime functions.

备注:如果读不懂的话,你只需要记住一点LC_ALL影响所有的就行了,至于其他的,可以用到再慢慢研究。

2.1、第二个参数:const char *locale(一)

2.1.1、必须支持的
地域设置名称说明
“C”默认的地域设置,C语言程序启动时就使用"C"地域设置,也就是相当于调用setlocale(LC_ALL,“C”)。"C"它会尽量少地包含默认地域设置信息,这些信息只是让C语言程序能够正常运行。 A value of C specifies the minimal ANSI conforming environment for C translation. The C locale assumes that all char data types are 1 byte and that their value is always less than 256.
“”使用当前操作系统默认的地域设置。Sets the locale to the default, which is the user-default ANSI code page obtained from the operating system.
NULL不指定任何名称。此时 setlocale() 不会对地域设置进行任何修改,仅仅是返回当前地域设置的名称。换句话说,如果我们仅仅想知道当前使用的是哪种地域设置,而不想修改它,那么就可以将 locale 参数置为 NULL。If the locale argument is a null pointer, the program’s current locale setting isn’t changed. Instead, setlocale returns a pointer to the string that’s associated with the category of the thread’s current locale.
2.1.2、设置为其他字符集

参见 2.2、设置为其他字符集

2.2、第二个参数:const char *locale(二)设置为其他字符集

linux和windows情况不同,跨平台时需要考虑。(当然,最后不要全局设置)
Linux 下的 locale 只有一种格式,而 Windows 下的 locale 有三种格式。

2.2.1 windows环境
  • 1、专有名称
    Windows 定义了一组专有的地域设置名称供 setlocale() 使用,这些名称包含了地域设置的所有信息,例如:

setlocale (“LA_ALL”, “en-US”); //en-US就是一个专有名称,它对应的是美国英语
setlocale (“LC_CTYPE”, “zh-CN”); //zh-CN就是一个专有名称,它对应的是大陆汉语

不同的 Windows 版本支持不同的专有名称,大家在使用时注意查看手册。Windows 各个版本支持的所有名称请猛击: https://msdn.microsoft.com/en-us/library/cc233982.aspx

  • 2、语言 + 地区 + 代码页
    使用 setlocale() 进行地域设置时,还可以按照下面的格式来设置 locale 参数:

language_area.codepage

language 表示语言,例如英语或中文;
area 表示使用该语言的地区,例如美国或者中国大陆;
codepage 表示代码页,例如 GBK 编码的代码页是936。

举一个简单的例子:

chs_china.936
chs 是“chinese-simplified”的简写,表示简体中文,china 表示中国大陆,936 是 GBK 编码的代码页。

可以省略 area 和 codepage,只写 language,此时会选择当前 language 的默认 area 和 codepage;如此一来,上例就可以简写为chs。GBK 是简体中文版 Windows 默认的编码,它的代码页就是 936。

language字段的可用值参考:Language Strings
area字段的可用值参考:Country/Region Strings
codepage 字段的可用值是 Windows 系统支持的代码页编号,参考:代码页标识符Code Page Identifiers

  • 3、代码页
    字符编码就是使用某种语言的某个地区定义的文字在计算机内部的表示方式,代码页就是字符编码在计算机中的 ID,知道了代码页也就知道使用哪个地区的哪种语言了。

使用代码页的格式为:

.codepage

例如,

setlocale(“LC_ALL”, “.936”);就表示使用 GBK 编码,对应的是使用汉语的中国大陆地区。
例如,setlocale(“LC_ALL”, “.65001”);就表示使用UTF-8 编码

参见:
1.C语言和C++中locale设置
2.Windows setlocale()区域设置格式说明以及名称汇总
3.如何查看windows操作系统当前使用的字符集

2.2.2 linux环境

在 Linux 下,locale 的命名格式为:

language_area.charset

language 表示语言,例如英语或中文;
area 表示使用该语言的地区,例如美国或者中国大陆;
charset 表示字符集编码,例如 UTF-8 或者 GBK。

举一个简单的例子:

zh_CN.UTF-8
zh 代表中文,CN 代表大陆地区,UTF-8 表示字符集编码。

charset 可以省略,此时会选择当前语言的默认 charset。Linux 发行版大都使用 UTF-8 编码,它是 Unicode 字符集的一种编码方式,能够支持世界上的所有语言;省略 charset,也就意味使用 UTF-8。

参见:Linux setlocale()区域设置格式说明以及名称汇总

三、localeconv简介

贴下locale.h中的对localeconv的介绍。

Retrieves the values provided in the current locale object to format parameters for quantities. These are returned in an object of type struct lconv (see lconv for the description of its members).
简单翻译:localeconv可以用来获取当前的locale.获取的locale信息存储在lconv的结构体中。(locnv中有哪些参数,可以去上面的网址查看)

  • 对获取locale的函数localeconv,我们不过多介绍,只贴一段程序,感兴趣的可以深入的研究。
/* localeconv example */
#include <iostream>
#include <stdio.h>      /* printf */
#include <locale.h>     /* setlocale, LC_MONETARY, struct lconv, localeconv */

int main()
{
	setlocale(LC_ALL, "en_US");
	struct lconv * lc;
	lc = localeconv();
	printf("Local Currency Symbol: %s\n", lc->currency_symbol);
	printf("International Currency Symbol: %s\n", lc->int_curr_symbol);
	return 0;
}
  • 程序输出

Local Currency Symbol: $
International Currency Symbol: USD

四、_wsetlocale、setlocale

  • _wsetlocale是setlocale的宽字符版本,这两个函数的区别只在于返回值以及第二个参数使用的是否宽字符字符串,执行效果都是一样的。
    参见:[C/C++宽字符与控制台输出

五、setlocale()实战

gbk2312其实有多个版本的,比如GB2312-80这个版本就不包含"镕",“堃”,“趙”,"錢"等字符。而最新的gbk2312版本却包含。

#include <locale.h>

int main()
{
	    char* sl1 = setlocale(LC_ALL, "");
		int i;
		char str[10][4] = { "镕","堃","趙","錢","孫","李","周","吳","鄭","王" };
		printf("系统默认地域设置:");
		for (i = 0; i < 10; i++) {
			printf("%s", str[i]);
		}
		char* sl = setlocale(LC_ALL , ".20936");  //.20936代表GB2312-80;20936和936不同

		printf("\nGB2312-80设置:");
		char str2[10][4] = { "镕","堃","趙","錢","孫","李","周","吳","鄭","王" };
		for (i = 0; i < 10; i++) {
			printf("%s", str2[i]);
		}
		printf("\n");
		return 0;
}

输出

系统默认地域设置:镕堃趙錢孫李周吳鄭王
GB2312-80设置:???李周?王
在这里插入图片描述

六、常用代码页

代码页 国家(地区)或语言
437 美国
708 阿拉伯文(ASMO 708)
720 阿拉伯文(DOS)
850 多语言(拉丁文 I)
852 中欧(DOS) - 斯拉夫语(拉丁文 II)
855 西里尔文(俄语)
857 土耳其语
860 葡萄牙语
861 冰岛语
862 希伯来文(DOS)
863 加拿大 - 法语
865 日耳曼语
866 俄语 - 西里尔文(DOS)
869 现代希腊语
874 泰文(Windows)
932 日文(Shift-JIS)
936 中国 - 简体中文(GB2312)
949 韩文
950 繁体中文(Big5)
1200
Unicode
1201 Unicode (Big-Endian)
1250 中欧(Windows)
1251 西里尔文(Windows)
1252 西欧(Windows)
1253 希腊文(Windows)
1254 土耳其文(Windows)
1255 希伯来文(Windows)
1256 阿拉伯文(Windows)
1257 波罗的海文(Windows)
1258 越南文(Windows)
20866 西里尔文(KOI8-R)
21866 西里尔文(KOI8-U)
28592 中欧(ISO)
28593 拉丁文 3 (ISO)
28594 波罗的海文(ISO)
28595 西里尔文(ISO)
28596 阿拉伯文(ISO)
28597 希腊文(ISO)
28598 希伯来文(ISO-Visual)
38598 希伯来文(ISO-Logical)
50000 用户定义的
50001 自动选择
50220 日文(JIS)
50221 日文(JIS-允许一个字节的片假名)
50222 日文(JIS-允许一个字节的片假名 - SO/SI)
50225 韩文(ISO)
50932 日文(自动选择)
50949 韩文(自动选择)
51932 日文(EUC)
51949 韩文(EUC)
52936 简体中文(HZ)
65000 Unicode (UTF-7)
65001 Unicode (UTF-8)

1.如何查看windows操作系统当前使用的字符集


版权声明:本文为junxuezheng原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。