C标准库源码解剖(10):区域设置函数locale.h
2016-07-29 00:00
309 查看
国家、文化和语言规则集称为区域设置,locale.h头文件中定义了区域设置相关的函数。setlocale函数用于设置或返回当前的区域特性,localeconv用于返回当前区域中的数字和货币信息(保存在struct lconv结构实例中)。setlocale的第一个实参指定要改变的区域行为类别,预定义的setlocale类别有:
LC_ALL:所有行为。
LC_COLLATE:strcoll和strxfrm函数的行为。
LC_CTYPE:ctype.h中的字符串处理函数行为。
LC_MONETARY:localeconv返回的币值信息。
LC_NUMERIC:localeconv返回的小数点和非币值信息。
LC_TIME:strftime函数的行为。
locale.h中内容如下:
setlocale函数的实现代码比较复杂,这里就不解剖了。localeconv函数的代码比较简单,它先创建一个struct lconv实例result用来保存返回的信息,然后用编译器的内部宏来获取数字和货币的各个成员值,存入result中,然后返回。如下:
LC_ALL:所有行为。
LC_COLLATE:strcoll和strxfrm函数的行为。
LC_CTYPE:ctype.h中的字符串处理函数行为。
LC_MONETARY:localeconv返回的币值信息。
LC_NUMERIC:localeconv返回的小数点和非币值信息。
LC_TIME:strftime函数的行为。
locale.h中内容如下:
/* ISO C99 Standard: 7.11 本地化 <locale.h> */ #ifndef _LOCALE_H #define _LOCALE_H 1 #include <features.h> #define __need_NULL #include <stddef.h> #include <bits/locale.h> __BEGIN_DECLS /* 下面是setlocale第一个实参可能的值。代码假设LC_*宏的最小值为0 */ #define LC_CTYPE __LC_CTYPE #define LC_NUMERIC __LC_NUMERIC #define LC_TIME __LC_TIME #define LC_COLLATE __LC_COLLATE #define LC_MONETARY __LC_MONETARY #define LC_MESSAGES __LC_MESSAGES #define LC_ALL __LC_ALL #define LC_PAPER __LC_PAPER #define LC_NAME __LC_NAME #define LC_ADDRESS __LC_ADDRESS #define LC_TELEPHONE __LC_TELEPHONE #define LC_MEASUREMENT __LC_MEASUREMENT #define LC_IDENTIFICATION __LC_IDENTIFICATION __BEGIN_NAMESPACE_STD /* 获取数字和货币记号的结构 */ struct lconv { /* 数字(非币值)信息 */ char *decimal_point; /* 数字的小数点号 */ char *thousands_sep; /* 数字的千分组分隔符 */ /* 每个元素为相应组中的数字位数,索引越高的元素越靠左边。一个值为CHAR_MAX的元素表示没有更多 的分组了。一个值为0的元素表示前面的元素能用在靠左边的所有分组中 */ char *grouping; /* 数字分组分隔符 */ /* 货币信息 */ /* 前面的三个字符ISO 4217中规定的货币符号,第四个字符是分隔符,第五个字符是'/0' */ char *int_curr_symbol; char *currency_symbol; /* 本地货币符号 */ char *mon_decimal_point; /* 货币的小数点号 */ char *mon_thousands_sep; /* 倾向的千分组分隔符 */ char *mon_grouping; /* 类似于grouping元素(参考上面) */ char *positive_sign; /* 正币值的符号 */ char *negative_sign; /* 负币值的符号 */ char int_frac_digits; /* 国际币值的小数部分 */ char frac_digits; /* 本地币值的小数部分 */ /* 如果currency_symbol放在正币值之前则为1,否则为0 */ char p_cs_precedes; /* 当且仅当currency_symbol与正币值之间用空格分开时为1 */ char p_sep_by_space; /* 如果currency_symbol放在负币值之前则为1,否则为0 */ char n_cs_precedes; /* 当且仅当currency_symbol与负币值之间用空格分开时为1 */ char n_sep_by_space; /* 正值和负值符号的定位: 0 用圆括号括住数量和currency_symbol 1 正负号放在数量和currency_symbol之前 2 正负号放在数量和currency_symbol之后 3 正负号正好放在currency_symbol之前 4 正负号正好放在currency_symbol之后 */ char p_sign_posn; char n_sign_posn; #ifdef __USE_ISOC99 /* 如果int_curr_symbol放在正币值之前则为1,否则为0 */ char int_p_cs_precedes; /* 当且仅当int_curr_symbol与正币值之间用空格分开时为1 */ char int_p_sep_by_space; /* 如果int_curr_symbol放在负币值之前则为1,否则为0 */ char int_n_cs_precedes; /* 当且仅当int_curr_symbol与负币值之间用空格分开时为1 */ char int_n_sep_by_space; /* 正值和负值符号的定位: 0 用圆括号括住数量和int_curr_symbol 1 正负号放在数量和int_curr_symbol之前 2 正负号放在数量和int_curr_symbol之后 3 正负号正好放在int_curr_symbol之前 4 正负号正好放在int_curr_symbol之后 */ char int_p_sign_posn; char int_n_sign_posn; #else char __int_p_cs_precedes; char __int_p_sep_by_space; char __int_n_cs_precedes; char __int_n_sep_by_space; char __int_p_sign_posn; char __int_n_sign_posn; #endif }; /* 设置或返回当前的区域特性 */ extern char *setlocale (int __category, __const char *__locale) __THROW; /* 返回当前区域中的数字和货币信息 */ extern struct lconv *localeconv (void) __THROW; __END_NAMESPACE_STD /* 下面是一些扩展 */ __END_DECLS #endif /* locale.h */
setlocale函数的实现代码比较复杂,这里就不解剖了。localeconv函数的代码比较简单,它先创建一个struct lconv实例result用来保存返回的信息,然后用编译器的内部宏来获取数字和货币的各个成员值,存入result中,然后返回。如下:
/* localeconv.c:localeconv函数的实现 */ #include <locale.h> #include "localeinfo.h" #include <shlib-compat.h> /* 返回当前区域中的数字和货币信息 */ struct lconv * __localeconv (void) { static struct lconv result; /* 用于保存返回值的lconv类型实例 */ result.decimal_point = (char *) _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT); result.thousands_sep = (char *) _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP); result.grouping = (char *) _NL_CURRENT (LC_NUMERIC, GROUPING); if (*result.grouping == CHAR_MAX || *result.grouping == (char) -1) result.grouping = (char *) ""; result.int_curr_symbol = (char *) _NL_CURRENT (LC_MONETARY, INT_CURR_SYMBOL); result.currency_symbol = (char *) _NL_CURRENT (LC_MONETARY, CURRENCY_SYMBOL); result.mon_decimal_point = (char *) _NL_CURRENT (LC_MONETARY, MON_DECIMAL_POINT); result.mon_thousands_sep = (char *) _NL_CURRENT (LC_MONETARY, MON_THOUSANDS_SEP); result.mon_grouping = (char *) _NL_CURRENT (LC_MONETARY, MON_GROUPING); if (*result.mon_grouping == CHAR_MAX || *result.mon_grouping == (char) -1) result.mon_grouping = (char *) ""; result.positive_sign = (char *) _NL_CURRENT (LC_MONETARY, POSITIVE_SIGN); result.negative_sign = (char *) _NL_CURRENT (LC_MONETARY, NEGATIVE_SIGN); result.int_frac_digits = *(char *) _NL_CURRENT (LC_MONETARY, INT_FRAC_DIGITS); result.frac_digits = *(char *) _NL_CURRENT (LC_MONETARY, FRAC_DIGITS); result.p_cs_precedes = *(char *) _NL_CURRENT (LC_MONETARY, P_CS_PRECEDES); result.p_sep_by_space = *(char *) _NL_CURRENT (LC_MONETARY, P_SEP_BY_SPACE); result.n_cs_precedes = *(char *) _NL_CURRENT (LC_MONETARY, N_CS_PRECEDES); result.n_sep_by_space = *(char *) _NL_CURRENT (LC_MONETARY, N_SEP_BY_SPACE); result.p_sign_posn = *(char *) _NL_CURRENT (LC_MONETARY, P_SIGN_POSN); result.n_sign_posn = *(char *) _NL_CURRENT (LC_MONETARY, N_SIGN_POSN); result.int_p_cs_precedes = *(char *) _NL_CURRENT (LC_MONETARY, INT_P_CS_PRECEDES); result.int_p_sep_by_space = *(char *) _NL_CURRENT (LC_MONETARY, INT_P_SEP_BY_SPACE); result.int_n_cs_precedes = *(char *) _NL_CURRENT (LC_MONETARY, INT_N_CS_PRECEDES); result.int_n_sep_by_space = *(char *) _NL_CURRENT (LC_MONETARY, INT_N_SEP_BY_SPACE); result.int_p_sign_posn = *(char *) _NL_CURRENT (LC_MONETARY, INT_P_SIGN_POSN); result.int_n_sign_posn = *(char *) _NL_CURRENT (LC_MONETARY, INT_N_SIGN_POSN); return &result; } versioned_symbol (libc, __localeconv, localeconv, GLIBC_2_2); #if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_2) strong_alias (__localeconv, __localeconv20) compat_symbol (libc, __localeconv20, localeconv, GLIBC_2_0); #endif
相关文章推荐
- 并查集
- 一个简单的CD唱片管理程序
- Mockito:一个强大的用于Java开发的模拟测试框架
- 如何解决秒杀的性能问题和超卖的讨论
- 我的C实践(3):用宏和位运算来实现整数集合
- zlib库剖析(2):编译及应用
- Python性能优化指南
- Linux内存管理(5):分页机制和管理区初始化
- 成为Java GC专家(4):Apache的MaxClients参数及其对Tomcat执行Full GC的影响
- Java垃圾回收精粹
- Detour开发包介绍(2):使用
- 服务器设计系列:内存管理
- 深入理解Java反射:候捷谈Java反射机制
- 递归与分治策略
- libxml2剖析(4):XML技术概览
- Web负载均衡的几种实现方式
- Java集合框架官方教程(4):Set/List/Map/Queue/Deque实现
- C++ Primer学习心得和遇到的问题
- C标准库源码解剖(4):字符串处理函数string.h和wchar.h
- NoSQL数据库面面观