使 gzprintf 忽略语言环境 LC_NUMERIC
Make gzprintf ignore locale LC_NUMERIC
如何让 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 的样本写入文件但尚未对其进行基准测试。
不仅用 setlocale
包装每个调用可能会很慢。它是完全线程不安全的,因此在 general/library 代码中使用是不安全的。
假设您使用的是 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")
并保持原样。这不是库代码中的 valid/acceptable,但如果你正在编写库代码,你可以放弃并让调用者负责执行它认为合适的方法(永远不要尊重 LC_NUMERIC
,或使用newlocale
/uselocale
切换)。您可以只在其合同文档中写下此要求,并将未能遵守合同视为未定义,或者您可以通过断言 localeconv()->decimal_point
指向一个来主动测试非 '.'
基数点string "."
(并返回错误或如果无法保持则中止)。
如何让 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 的样本写入文件但尚未对其进行基准测试。
不仅用 setlocale
包装每个调用可能会很慢。它是完全线程不安全的,因此在 general/library 代码中使用是不安全的。
假设您使用的是 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")
并保持原样。这不是库代码中的 valid/acceptable,但如果你正在编写库代码,你可以放弃并让调用者负责执行它认为合适的方法(永远不要尊重 LC_NUMERIC
,或使用newlocale
/uselocale
切换)。您可以只在其合同文档中写下此要求,并将未能遵守合同视为未定义,或者您可以通过断言 localeconv()->decimal_point
指向一个来主动测试非 '.'
基数点string "."
(并返回错误或如果无法保持则中止)。