您的位置:首页 > 其它

C标准库源码解剖(10):区域设置函数locale.h

2016-07-29 00:00 429 查看
国家、文化和语言规则集称为区域设置,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中内容如下:

/* 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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: