6.7 多字节字符和宽字符介绍了标准库的国际化。本节讨论受影响的库函数,并提供一些关于应如何编写程序以便利用这些功能的提示。本节只讨论关于 1990 ISO/IEC C 标准的国际化。1999 ISO/IEC C 标准并未进行重大扩展以支持高于此处讨论的国际化。
任何时候,C 程序都有当前语言环境-描述适合于某个民族、文化和语言的惯例的信息集合。语言环境具有字符串名称。唯一的两个标准化语言环境名称为 "C" 和 ""。每个程序在 "C" 语言环境中启动,这导致所有库函数像过去一样工作。"" 语言环境是实现在选择适合程序的调用的正确惯例集时的首选。"C" 和 "" 可导致相同的行为。实现可能提供其他语言环境。
为了实用和方便,语言环境被划分为一系列种类。程序可更改整个语言环境,或者只更改一个或多个种类。通常,每个种类影响与受其他种类影响的函数分开的函数集,因此可以临时更改一个种类。
setlocale() 函数是指向程序语言环境的接口。通常,使用调用国家惯例的任何程序在程序执行路径的开头部分应发出一个调用,如:
#include <locale.h> /*...*/ setlocale(LC_ALL, ""); |
。该调用导致程序的当前语言环境更改为相应的本地版本,因为 LC_ALL 是指定整个语言环境而不是某个种类的宏。以下是标准种类:
LC_COLLATE |
排序信息 |
LC_CTYPE |
字符分类信息 |
LC_MONETARY |
货币输出信息 |
LC_NUMERIC |
数值输出信息 |
LC_TIME |
日期和时间输出信息 |
这些宏中的任何宏均可作为 setlocale() 的第一个参数传递以指定该种类。
setlocale() 函数返回给定种类的当前语言环境的名称(或 LC_ALL),当其第二个参数为空指针时,它仅用于查询。因此,如下代码可用于在有限持续时间内更改语言环境或其中一部分:
#include <locale.h> /*...*/ char *oloc; /*...*/ oloc = setlocale(LC_category, NULL); if (setlocale(LC_category, "new") != 0) { /* use temporarily changed locale */ (void)setlocale(LC_category, oloc); } |
大多数程序不需要此功能。
只要可能并且适当,就会将现有库函数扩展为包括与语言环境相关的行为。这些函数分为两组:
ctype.h 头文件声明的函数(字符分类和转换),以及
转换为和转换自数值的可输出形式和内部形式的函数,如 printf() 和 strtod()。
对于附加字符,如果当前语言环境的 LC_CTYPE 种类不是 "C",则除 isdigit() 和 isxdigit() 之外的所有 ctype.h 判定函数都可返回非零(真)值。在西班牙语言环境中,isalpha(’ñ’) 应为真。同样,字符转换函数 tolower() 和 toupper() 应相应地处理 isalpha() 函数标识的任何额外字母字符。ctype.h 函数通常是使用由字符参数索引的查表而实现的宏。通过将表重新设置为新语言环境的值可更改这些函数的行为,因此没有性能影响。
当前语言环境的 LC_NUMERIC 种类不是 "C" 时,写入或解释可输出浮点值的那些函数可以更改为使用非句点 (.) 的小数点字符。不存在将任何数值转换为包含千位分隔符类型字符的可输出形式的规定。从可输出形式转换为内部形式时,允许实现接受此类附加形式,同样是在非 "C" 语言环境中。使用小数点字符的函数是 printf() 和 scanf() 系列、atof() 以及 strtod()。允许实现定义的扩展的函数是 atof()、atoi()、atol()、strtod()、strtol()、strtoul() 和 scanf() 系列。
某些语言环境相关的功能是以新标准函数的形式添加的。除了 setlocale()(它允许控制语言环境本身)之外,该标准还包括以下新函数:
localeconv() |
数值/货币转换 |
strcoll() |
两个字符串的整理顺序 |
strxfrm() |
转换字符串以便整理 |
strftime() |
设置日期和时间的格式 |
此外,还有多字节函数 mblen()、mbtowc()、mbstowcs()、wctomb() 和 wcstombs()。
localeconv() 函数返回一个指针,该指针指向包含对设置数值格式有用的信息以及适合当前语言环境的 LC_NUMERIC 和 LC_MONETARY 种类的货币信息的结构。这是唯一的一个其行为依赖于多个种类的函数。对于数值,结构描述小数点字符、千位分隔符和分隔符应在的位置。有十五个描述如何格式化货币值的其他结构成员。
strcoll() 函数类似于 strcmp() 函数,只是它根据当前语言环境的 LC_COLLATE 种类比较两个字符串。strxfrm() 函数也可用于将一个字符串转换为另一个字符串, 以便任何两个此类转换后字符串均可以传递到 strcmp(),并且可获得与 strcoll() 传递两个预转换字符串时返回的排序类似的排序。
strftime() 函数提供与 sprintf() 对 struct tm 中的值使用的格式设置类似的格式设置,并提供依赖当前语言环境的 LC_TIME 种类的某些日期和时间表示。此函数基于 ascftime() 函数,后者作为 UNIX System V 发行版 3.2 的一部分发行。