使gzprintf忽略语言环境LC_NUMERIC

时间:2018-11-08 14:26:36

标签: c locale zlib

如何使gzprintf(或一般来说是printf)使用“。”作为小数点分隔符,可以有效地忽略LC_NUMERIC或使用“ LC_NUMERIC = C”。

背景:我的程序使用gettext进行setlocale (LC_ALL, ....)来更改其语言环境。但有一点我需要写入一个测量文件,该文件应具有固定的“”。作为小数点分隔符。我当然可以做类似的事情

const char *old = setlocale (LC_NUMERIC, NULL);
... make copy
setlocale (LC_NUMERIC, "C");
... use gzprintf
setlocale (LC_NUMERIC, old_copy);

但是我担心运行时出现问题,因为我必须向文件中写入2kHz的样本,但尚未对其进行基准测试。

1 个答案:

答案 0 :(得分:2)

不仅每次通话都用setlocale包装,这样可能会很慢。这是完全线程不安全的,因此在一般/库代码中使用是不安全的。

假设您使用的是POSIX或类似POSIX的系统,那么您需要的是newlocale / uselocale。一次执行以下操作(可能会很慢)并保存结果:

locale_t safe_locale = newlocale(LC_NUMERIC_MASK, "C", duplocale(LC_GLOBAL_LOCALE));

然后,每当您要使用它时:

locale_t old = uselocale(safe_locale);
/* Do stuff with it. */
uselocale(old);

您不必在每次操作之前来回切换,仅在返回可能期望其语言环境不受干扰的调用者之前,但是无论如何像这样来回切换都不会太慢。

或者,根本不尊重您的应用程序中的LC_NUMERIC。调用setlocale(LC_ALL, "")根据用户设置设置语言环境后,请调用setlocale(LC_NUMERIC, "C")并保持原来的状态。这在库代码中是无效/不可接受的,但是如果您正在编写库代码,则可以平移并让调用者负责执行它认为合适的任何方法(绝对不要兑现LC_NUMERIC或使用{{ 1}} / newlocale进行切换)。您既可以在合同的文档中写下此要求,也可以将未履行合同的情况视为未定义,或者可以通过断言uselocale指向非'.'基数来积极测试字符串localeconv()->decimal_point(并返回错误或如果失败则中止)。

相关问题