- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
C99 标准的第 7.11 节描述了 <locale.h>
header 及其内容。特别是,它定义了 struct lconv
并表示:
[...] In the "C" locale, the members shall have the values specified in the comments.
char *decimal_point; // "."
char *thousands_sep; // ""
char *grouping; // ""
char *mon_decimal_point; // ""
char *mon_thousands_sep; // ""
char *mon_grouping; // ""
char *positive_sign; // ""
char *negative_sign; // ""
char *currency_symbol; // ""
char frac_digits; // CHAR_MAX
char p_cs_precedes; // CHAR_MAX
char n_cs_precedes; // CHAR_MAX
char p_sep_by_space; // CHAR_MAX
char n_sep_by_space; // CHAR_MAX
char p_sign_posn; // CHAR_MAX
char n_sign_posn; // CHAR_MAX
char *int_curr_symbol; // ""
char int_frac_digits; // CHAR_MAX
char int_p_cs_precedes; // CHAR_MAX
char int_n_cs_precedes; // CHAR_MAX
char int_p_sep_by_space; // CHAR_MAX
char int_n_sep_by_space; // CHAR_MAX
char int_p_sign_posn; // CHAR_MAX
char int_n_sign_posn; // CHAR_MAX
第 7.11.2.1 节“localeconv() 函数”接着说:
The members of the structure with type
char *
are pointers to strings, any of which (exceptdecimal_point
) can point to""
, to indicate that the value is not available in the current locale or is of zero length. [...] The members with type char are nonnegative numbers, any of which can beCHAR_MAX
to indicate that the value is not available in the current locale.
它继续讨论每个成员。你可以看到 4 个组,每组 3 个成员,一个代表组是 p_cs_precedes
, p_sep_by_space
和 p_sign_posn
。
char p_cs_precedes
Set to 1 or 0 if the currency_symbol respectively precedes or succeeds the value for a nonnegative locally formatted monetary quantity.
char p_sep_by_space
Set to a value indicating the separation of the currency_symbol, the sign string, and the value for a nonnegative locally formatted monetary quantity.
char p_sign_posn
Set to a value indicating the positioning of the positive_sign for a nonnegative locally formatted monetary quantity.
给出了p_sign_posn
的详细解释;它们对这个问题并不重要。
该标准还给出了一些如何解释这些类型的示例。
如果您找到原始的 C99 标准 (ISO/IEC 9899:1999),请注意 TC1(国际标准 ISO/IEC 9899:1999 技术勘误 1,发布于 2001-09-01)和 TC2(国际标准 ISO/IEC 9899:1999 Technical Corrigendum 2, published 2004-11-15) 对 §7.11.2.1 进行了更改(但 TC3 没有)。但是,这些更改既不解决也不影响我将要问的问题的答案。
我的前两个问题是关于四个三元组(cs_precedes、sep_by_space 和 sign_posn),而其他更一般的问题是关于什么构成有效语言环境:
如果合理,应该如何解释这些组合?
定义了两个组合(所有值都设置为 CHAR_MAX
,如在 "C"
语言环境中,并且所有值都有效设置);我很好奇的是其他 6 个混合设置。
如果定义了三元组但相关的货币符号没有定义,那么区域设置是否正确?
我的倾向是回答:
frac_digits
或时才需要货币小数点int_frac_digits
大于零)。一个实现可能会强制执行这些规则,但可以想象另一个实现会以不同的方式解释规则并得出不同的结论。
你怎么说?
最佳答案
据我所知,标准 C 和 POSIX 都没有规定任何关于在 struct lconv
中有效和无效的规则。 .一个可能的原因是标准 C 或 POSIX 中没有函数采用 struct lconv
。作为论点;只有 localeconv()
函数返回结构:
struct lconv *localeconv(void);
因此,由于实现名义上是 struct lconv
的唯一来源值(value)观,无论实现做什么,在实现眼中都必须是好的。总而言之,它有点像胎死腹中的特征;它提供了没有任何东西可以直接使用的功能。然而,在幕后,部分信息得到了支持(首先想想 printf()
和 scanf()
等)。货币信息不被任何标准 C 函数使用。它们(<locale.h>
header 和 localeconv()
和 setlocale()
函数)由委员会添加到 C89,部分是为了确保 C 可以有一个单一的 ISO 标准,与 ANSI 标准相同C.
Plauger 的书 ' The Standard C Library '(它实现了 C89 标准库)提供了一个名为 _Fmtval()
的函数它可用于使用当前语言环境的约定来格式化国际货币、国家(本地)货币和数字,但再次强调,所使用的结构由实现定义,而不是由用户提供。
POSIX 确实提供了一对函数 strfmon()
and strfmon_l()
,后者需要 locale_t
作为论点之一。
ssize_t strfmon(char *restrict s, size_t maxsize, const char *restrict format, ...);
ssize_t strfmon_l(char *restrict s, size_t maxsize, locale_t locale,
const char *restrict format, ...);
但是,POSIX 对 locale_t
类型的内容没有任何说明。 ,尽管它确实提供了以下功能来以有限的方式操纵它们:
locale_t duplocale(locale_t)
void freelocale(locale_t)
locale_t newlocale(int, const char *, locale_t)
locale_t uselocale (locale_t)
但是,这些提供了一种最小化和不干涉的方法来操纵语言环境,并且绝对不会详细说明在 struct lconv
中什么可以接受或不可以接受。 .还有 nl_langinfo()
功能:
#include <langinfo.h>
char *nl_langinfo(nl_item item);
char *nl_langinfo_l(nl_item item, locale_t locale);
这些允许您使用诸如 ABDAY_1
之类的名称,一次找到一个项目,区域设置的各个部分的值。找出第 1 天的缩写名称,在英语语言环境中为“Sun”。 <langinfo.h>
中大约有 55 个这样的名字.有趣的是,这套装置并不完整;您无法通过这种方式找到国际货币符号。
鉴于两个主要相关标准都没有对struct lconv
的内容进行约束。 ,我们只剩下尝试确定实际约束。
(旁白:考虑到 C99 标准中国家和国际格式化信息的对称性,在某些方面遗憾的是没有使用结构来编码信息;它使得繁琐的代码将正确的点点滴滴挑选成通用函数。一些字段( cs_precedes
, sep_by_space
)也可能是 bool 值,但 <stdbool.h>
不在 C89 中。)
重述问题:
My first two questions are about the four triples (
cs_precedes
,sep_by_space
, andsign_posn
), and the others more general questions about what constitutes a valid locale:
- Is it feasible or sensible to have one or two of the members of a triple with the CHAR_MAX designation while the other members have values in the normal range (0-1, 0-1, 0-4)?
- If it is sensible, how should the combinations be interpreted?
- Is a locale properly formed if the triples are defined but the relevant currency symbol is not?
- Is a locale properly formed if the monetary decimal point is not defined but the currency symbol is defined.
- If the sign position is not 0 (indicating that a value is surround by parentheses), is a locale properly formed if the currency symbol is set but both the positive and negative sign strings are empty?
- Does it make sense for the positive triple to be defined when the negative triple is not?
原始的大纲答案是:
- No; either all or none of the members of a triple should be set to CHAR_MAX.
- Not applicable given the answer to (1).
- No.
- No (but there is a borderline case for the old Italian currency (lire) where there were no fractions and so no decimal point was needed; that could be handled with a condition that the monetary decimal point is only needed if
frac_digits
orint_frac_digits
is greater than zero).- No.
- No.
我花了一些时间实现代码来处理这样的格式设置,在我看来,我原来的答案基本上是正确的。
我最终实现的验证语言环境的代码是:
/* Locale validation */
#define VALUE_IN_RANGE(v, mn, mx) ((v) >= (mn) && (v) <= (mx))
#define ASSERT(condition) do { assert(condition); \
if (!(condition)) \
return false; \
} while (0)
#define ASSERT_RANGE(v, mn, mx) ASSERT(VALUE_IN_RANGE(v, mn, mx))
static bool check_decpt_thous_group(bool decpt_is_opt, const char *decpt,
const char *thous, const char *group)
{
/* Decimal point must be defined; monetary decimal point might not be */
ASSERT(decpt != 0);
ASSERT(decpt_is_opt || *decpt != '\0');
/* Thousands separator and grouping must be valid (non-null) pointers */
ASSERT(thous != 0 && group != 0);
/* Thousands separator should be set iff grouping is set and vice versa */
ASSERT((*thous != '\0' && *group != '\0') ||
(*thous == '\0' && *group == '\0'));
/* Thousands separator, if set, should be different from decimal point */
ASSERT(*thous == '\0' || decpt_is_opt ||
(*decpt != '\0' && strcmp(thous, decpt) != 0));
return true;
}
static bool currency_valid(const char *currency_symbol, char frac_digits,
char p_cs_precedes, char p_sep_by_space, char p_sign_posn,
char n_cs_precedes, char n_sep_by_space, char n_sign_posn)
{
ASSERT(currency_symbol != 0);
if (*currency_symbol == '\0')
{
ASSERT(frac_digits == CHAR_MAX);
ASSERT(p_cs_precedes == CHAR_MAX);
ASSERT(p_sep_by_space == CHAR_MAX);
ASSERT(p_sign_posn == CHAR_MAX);
ASSERT(n_cs_precedes == CHAR_MAX);
ASSERT(n_sep_by_space == CHAR_MAX);
ASSERT(n_sign_posn == CHAR_MAX);
}
else
{
ASSERT_RANGE(frac_digits, 0, 9); // 9 dp of currency is a lot!
ASSERT_RANGE(p_cs_precedes, 0, 1);
ASSERT_RANGE(p_sep_by_space, 0, 2);
ASSERT_RANGE(p_sign_posn, 0, 4);
ASSERT_RANGE(n_cs_precedes, 0, 1);
ASSERT_RANGE(n_sep_by_space, 0, 2);
ASSERT_RANGE(n_sign_posn, 0, 4);
}
return true;
}
static bool locale_is_consistent(const struct lconv *loc)
{
if (!check_decpt_thous_group(false, loc->decimal_point, loc->thousands_sep, loc->grouping))
return false;
if (!check_decpt_thous_group((loc->frac_digits == 0 || loc->frac_digits == CHAR_MAX),
loc->mon_decimal_point, loc->mon_thousands_sep, loc->mon_grouping))
return false;
/* Signs must be valid (non-null) strings */
ASSERT(loc->positive_sign != 0 && loc->negative_sign != 0);
/* Signs must be different or both must be empty string (and probably n_sign_posn == 0) */
ASSERT(strcmp(loc->positive_sign, loc->negative_sign) != 0 || *loc->negative_sign == '\0');
if (!currency_valid(loc->currency_symbol, loc->frac_digits,
loc->p_cs_precedes, loc->p_sep_by_space, loc->p_sign_posn,
loc->n_cs_precedes, loc->n_sep_by_space, loc->n_sign_posn))
return false;
if (!currency_valid(loc->int_curr_symbol, loc->int_frac_digits,
loc->int_p_cs_precedes, loc->int_p_sep_by_space, loc->int_p_sign_posn,
loc->int_n_cs_precedes, loc->int_n_sep_by_space, loc->int_n_sign_posn))
return false;
/*
** If set, international currency symbol must be 3 (upper-case)
** alphabetic characters plus non-alphanum separator
*/
if (*loc->int_curr_symbol != '\0')
{
ASSERT(strlen(loc->int_curr_symbol) == 4);
ASSERT(isupper(loc->int_curr_symbol[0]));
ASSERT(isupper(loc->int_curr_symbol[1]));
ASSERT(isupper(loc->int_curr_symbol[2]));
ASSERT(!isalnum(loc->int_curr_symbol[3]));
}
return true;
}
标准说 loc->int_curr_symbol[3]
在格式化国际货币时用作“空格”字符,允许字母字符以及 ISO 4217 国际货币代码(基本字母表中的三个大写字母)毫无意义。如果符号也是分开的,那么允许数字可能会导致混淆,所以我认为 !isalnum(loc->int_curr_symbol[3])
断言是明智的。严格检查将验证国际货币符号是否是 ISO 4217 中列出的符号之一;不过,这在编码上有点棘手!
关于c - 描述区域设置的 'struct lconv' 中的值的正式和实际限制是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8261684/
在一个环境中,我有 pandas 版本 0.17.0 和 numpy 版本 1.10.1。在另一个环境中,我有 pandas 版本 0.18.1 和 numpy 版本 1.10.4。 我运行这段代码
This question already has answers here: Default stringify for objects, equivalent to Java's toString
我一直在尝试为我的profile命令嵌入设置一个人们可以更改的简历。我认为它应该有效,但我的代码似乎有问题。 相关代码如下: const PREFIX = '!'; var bio = {}; cli
我正在尝试获取网站图标、网站标题和外部 URL 列表的描述,最好使用 jquery。我已经成功地为我的网址同步了谷歌的图标服务,任何人都可以阐明如何实现网站标题和描述吗?这是我到目前为止获得图标的内容
我在尝试运行代码时收到错误。找不到问题出在哪里。我可能遗漏了一些小细节,如果您能纠正它那就太好了。 计算Servlet import java.io.IOException; impo
我的数据库中有两个字段,一个是描述(TEXT),另一个是short_desc(VARCHAR-200)。 当我显示搜索结果时,我显然使用了short_desc,当有人点击该项目时,他们会得到完整的描述
当我尝试通过ajax和Jquery调用 Controller 上的save方法时,我正在使用Spring MVC、Jquery、Hibernate和tomcat。单击“保存”按钮时,我在 tomcat
我试图使用describe()来获取一些描述性统计数据,但获取了应该是数字的nan值。 我尝试使用 axis=0 或 axis=1,而 axis=1 产生了正确的数值,但这不是正确的数值我需要; ax
我有超过 1 亿个字符串要存储在文件系统中。与字符串 (~255Chars utf8) 一起,将有两个日期和一些定义其属性的整数值。 我可以将它们放在一个 CSV 文件中,但它会很大。我可以将几个较小
有没有办法将 JavaScript 合并到 Jenkins 顶部的描述字段中? 每当我添加脚本标签时,当您查看源代码时,它都会被 Jenkins 删除。 如果有人有建议或方向指出我,那就太好了。
您如何获得 SEH 的名称和/或描述?异常无需必须将字符串硬编码到您的应用程序中? 我尝试使用 FormatMessage(),但它有时会截断消息,即使您指定忽略插入也是如此: __asm { //
如果我在 MySQL 中使用 CREATE TRIGGER 语法创建一个触发器,我该如何附加注释来描述它?我的意思是在声明中或之后对我来说是一样的。 我想不通。对于表格,您可以在声明末尾添加 COMM
关闭。这个问题是opinion-based .它目前不接受答案。 想要改进这个问题? 更新问题,以便 editing this post 可以用事实和引用来回答它. 关闭 8 年前。 Improve
当开发多媒体应用或者游戏应用的时候,需要使用音量控制键来设置程序的音量大小。在Android系统中有多中音频流,通过Activity中的函数 setVolumeControlStream(int s
Slick DSL 允许通过两种方式在表中创建可选字段。 对于这个案例类: case class User(id: Option[Long] = None, fname: String, lname:
如果不属于默认命名空间,我如何描述 pod 信息。使用默认命名空间我没有任何问题。 但我想获得与命名空间对齐的特定 pod 的信息。 但是,当我想描述我可以制作的同一个 pod 时,请参阅 我尝试使用
在我使用过的几乎所有 vim 副本中,程序都会在替换文本后给出更改的描述。 (例如,将显示类似“20 行 92 个替换”之类的内容。) 我现在正在使用默认情况下不这样做的 vim 副本。 是否有一个简
我正在编写规范,需要描述一些 JSON 对象。单独的文本和选项卡往往会使大型 JSON 变得过于困惑。是否有任何在线(最好)工具可以创建类似于 http://www.json.org/ 上的图表的工具
我正在尝试通过 DNS 将我的 Kubernetes 部署连接在一起。 我有一个 Java (Spring Boot) 部署和一个 javascript (node.js) 部署,两者都通过默认的 C
我只是在学习 WebGL 图形编程。 我正在检查包含该语句的某人的代码 // multiply the position by the matrix. gl_Position = vec4((u_ma
我是一名优秀的程序员,十分优秀!