地区:可能是国家、洲或省活着一种特定的文化。
扩展:1994年通过的ISO C标准修正草案1
提供了编写额外国际化程序增加的额外库
- iso646.h
- wctype.h
- wchar.h
25.1 locale.h:本地化
标准库中依赖地区的部分:
- 数值的格式:例如,一些地区小数点是一个圆点(297.48),而在另一些地方则是逗号(297,48)
货币的格式:例如,不同国家的货币符号不同
字符集:例如,亚洲国家通常比西方国家需要更大的字符集
日期和时间的表示形式:例如,一些地方习惯在写日期时先写月(8/24/97),而另一些地方习惯先写日(24/8/97)
25.1.1 类别
说明:
locale.h
提供了一系列的以LC_
开头的宏来,这些宏分别对某些库的某些方面的行为产生影响。
扩展:C语言的实现提供了其它类型并且定义了上面未列出的以LC_
开头的宏。
宏 | 影响 | 头文件 | 相关章节 | 备注 |
---|---|---|---|---|
LC_COLLATE | strcoll函数 | string.h | 23.5 | 字符串比较函数 |
strxfrm函数 | string.h | 23.5 | 字符串比较函数 | |
LC_CTYPES | isdigit函数 | ctype.h | 23.4 | |
isxdigit函数 | ctype.h | 23.4 | ||
多字节函数 | stdlib.h | 25.2.1 | ||
LC_MONETARY | localeconv函数 | locale.h | 影响该函数返回的货币格式信息 | |
LC_NUMERIC | 格式化输入输出函数中使用的小数点字符 | stdio.h | 22 | 比如printf 和scanf |
字符串转换函数 | stdlib.h | 26.2.1 | atof 和strtod |
|
localeconv函数 | locale.h | 该函数返回的非货币格式信息 | ||
LC_TIME | strftime函数 | time.h | 26.3.2 | 该函数用于将时间转换为字符串 |
25.1.2 setlocale函数
描述:用来修改当前的地区,也可以用来获取当前地区的信息。
参数:
1: 可以针对一种类型,也可以针对所有类型
参数1取值 | 说明 |
---|---|
LC_COLLATE、LC_CTYPE、LC_MONETARY 、LC_NUMERIC、LC_TIME | 针对一种类型 |
LC_ALL | 针对所有类型 |
2: C语言标准为第二个参数仅定义了两种可能值:”c”或” “。其他地区可以针对不同的实现定义。
参数二取值 | 说明 | 备注 |
---|---|---|
"C" |
按正常方式执行,小数点是一个句点 | |
" " |
换到本地模式(native locale) |
C语言标准 没有定义切换到本地模式的具体影响 |
"Germany" |
德国 | 部分编译器支持 |
类似en_GB.WIN1252 格式的字符串 |
英语_英国.Windows多语言字符集 | 一些常用编译器支持 |
NULL |
不设置任何东西 | 仅仅返回指向与当前地区类型的设置相关联的字符串 |
技巧:如果需要获得与当前地区关联字符串,可以在调用setlocale函数时第一个参数给
LC_ALL
,第二个参数给NULL
.
原型:locale.h
1 | /** |
1 | // 任意程序执行开始时,都会隐含执行调用 |
1 | /* 获取地区信息字符串 */ |
25.1.3 localeconv函数
描述:获取当前地区的各种信息
原型:locale.h
1 | /** |
struct lconv
说明:存储当前地区的各种信息的结构体
结构成员:有char *
和char
两种类型
char *型成员 |
---|
char型成员 |
---|
p_sign_posn和n_sign_posn的值:
案例:用于美国和意大利两国的lconv结构成员的货币型常用值
25.2 多字节字符和宽字符
字符集(美国):
分类 | 地位 |
---|---|
ASCII | 主流计算机采用 |
EBCDIC | 其他计算机 |
可扩展字符集:C语言允许编译器提供一种可扩展的字符集
可扩展字符集编码 | 说明 |
---|---|
多字节字符(multibyte character) | 一个或多个字节表示一个可扩展的字符 |
宽字符(wide character) | 一种其值表示字符的整数,具有相同的字节数 |
基本字符:任何可扩展的字符集必须包含C语言要求的
基本字符
(即字母
、数字
、运算符
、标点符
、空白字符
),而且这些字符要求是单字节的。
用途:c语言同时提供了多字节字符和宽字符用于不同的目的
- 多字节字符:多用于输入/输出,因为输入/输出设备经常是面向字节的
- 宽字符:更适用于程序内部,因为没个宽字符占有相同的空间,便于程序内部操作。
技巧:程序可以读入多字节字符,然后转为便于程序内部操作的宽字符格式,谈后再把宽字符转换回用于输出的多字节格式。
25.2.1 多字节字符
空字符(
\0
):无论移位状态如何,c标准都要求\0
始终用来表示空字符。而且,\0
不能是多字节字符的第二个(或之后)字节。
按是否依赖状态分类:mblen函数
、mbtowc函数
、wctomb函数
都可用检测对字节字符是否是依赖状态的。只要其char *型参数给予NULL实参,则返回非零说明依赖状态;返回零说明依赖状态。
分类 | 说明 | 例子 |
---|---|---|
依赖状态编码(state-dependent enciding) | 每个多字节字符序列都以初始移位状态(initial shift state) 开始,序列中稍后遇到的一些多字节字符会改变移位状态,并且会影响后续字节的含义 |
日本的JIS编码 |
不依赖状态编码 | 每个字符要求一个或者两个字节,但是双字节字符的第一个字节可以始终区别与单字节字符 | 日本的Shift-JIS编码 |
相关宏:两个
宏 | 头文件 | 含义 | 备注 |
---|---|---|---|
MB_LEN_MAX | limit.h | 任意支持区域的最大值 | |
MB_CUR_MAX | stdlib.h | 当前区域的最大值 | 改变地区可能会影响多字节字符的解释 |
25.2.2 宽字符
说明:采用特殊实现(比如
unsigned short int
)支持的所有宽字符都要求相同的字节数。
宽字符类型:wchar_t
(stddef.h
、stdlib.h
)
宽字符常量和宽字符串常量:L字符(串)常量
- 宽字符常量:
L'a'
- 宽字符串常量:
L"abc"
Unicode
说明:非常重要的固定长度编码的字符集。
字符宽度:两个字节
25.2.3 多字节字符/宽字符转换函数
mblen函数
说明:检测s是否指向形成由效多字节字符的字节序列
原型:stdlib.h
1
2
3
4
5
6 /**
* @param {char *} s 多字节字符的字节序列
* @param {size_t} a 最多能将测的字节的数量(通常为MB_CUR_MAX)
* @return {int} 字符中的字节数:是多字节字符序列;0:空字符;-1:不是多字节字符序列
*/
int mblen(const char *s, size_t a);
1 | /** |
mbtowc函数
说明:将多字节字符串转换为宽字符
原型:stdlib.h.h
1 | /** |
wctomb函数
说明:把宽字符转换为多字节字符
原型:stdlib.h
1 | /** |
1 | /** |
25.2.4 多字节字符/宽字符串函数
mbstowcs函数
说明:把多字节字符序列转换为宽字符序列
- 如何进行转换依赖于当前地区的
LC_CTYPES
类别- 当达到上限或者遇到(存储在宽字符数组中的)
\0
时,函数停止- 假设要转换的字符串以初始迁移状态开始
原型:
stdlib.h
1 | /** |
wcstombs函数
说明:把宽字符序列转换为多字节字符序列
- 如何进行转换依赖于当前地区的
LC_CTYPES
类别- 当达到上限或者遇到(自己存入的)
\0
时,函数停止- 产生的字符串是以初始迁移状态开始的
原型:
stdlib.h
1 | /** |
25.3 三字符序列
三字符序列(trigraph sequence):简称“三字符”,是一种三个字符的字符码。以
??字符
的形式出现。
用途:可以替换ASCII中的一些特殊字符。
兼容性:尽管不是一直需要,但是所有标准C编译器都要求接受三字符序列。
技巧:字符串中的??
可能会被编译器作为三字符序列的开始标志,可以通过使用\
将第二个?
转义(即?\?
)来避免。
1 |
|
1 | ??=include <stdio.h> |