boost::lexical_cast<> 的语言环境不变保证

Posted

技术标签:

【中文标题】boost::lexical_cast<> 的语言环境不变保证【英文标题】:Locale invariant guarantee of boost::lexical_cast<> 【发布时间】:2013-09-29 14:22:45 【问题描述】:

我正在使用boost::lexical_cast&lt;std::string&gt;(double) 将双精度转换为字符串,生成 JSON 序列化字节流,即(在远程端)由 .NET 解析。

我能够强制 .NET 使用 InvariantCulture 进行解析,从而在每种可能的语言上返回可预测的结果。

但是,我无法在 boost::lexical_cast 文档中找到此保证。我试了一下,对于不同的语言环境,它的工作方式相同。但是,我不能仅从少数测试中确定,我是否遗漏了文档中的某些内容,或者这根本无法保证,我必须使用其他东西?

编辑: 我发现了一个问题。

std::locale::global(std::locale("Czech")); 
std::cout << boost::lexical_cast<std::string>(0.15784465) << std::endl;

返回0,15784465,这是不希望的。我可以强制boost::lexical_cast&lt;&gt; 不知道语言环境吗?

【问题讨论】:

Locale-invariant string processing with strtod strtof atof printf?的可能重复 考虑使用 sqlite printf,它是区域设置不变的,可以做你想做的事。包括在各种其他库中的所有 c++ 转换函数都依赖于语言环境。 【参考方案1】:

我可以强制 boost::lexical_cast 不注意语言环境吗?

不,我认为这是不可能的。你能做的最好的就是打电话

std::locale::global(std::locale::classic());

将全局语言环境设置为“C”语言环境,因为boost::lexical_cast 依赖于全局语言环境。但是,问题是如果在调用boost::lexical_cast 之前在代码中的其他位置将全局语言环境设置为其他位置,那么您仍然会遇到同样的问题。 因此,一个健壮的解决方案将是imbue 像这样的字符串流,您可以始终确定这是有效的:

std::ostringstream oss;
oss.imbue(std::locale::classic());
oss.precision(std::numeric_limits<double>::digits10);
oss << 0.15784465;

【讨论】:

从根本上说,问题在于 C++ 语言环境不是线程本地的、尊重 RAII 的属性。 您在多个语言环境 Windows 中保存了我的存档异常。非常感谢!【参考方案2】:

解决此问题的更好方法是使用boost::locale 代替 std::locale 作为全局语言环境。来自documentation:

设置全局语言环境会产生不良的副作用...它甚至会影响 printf 和诸如 boost::lexical_cast 之类的库,它们会给出不正确或意外的格式。事实上很多第三方库都是在这种情况下崩溃的。 与标准本地化库不同,Boost.Locale 从不更改基本数字格式,即使它使用基于 std 的本地化后端,所以默认情况下,数字总是使用 C 风格的语言环境进行格式化。本地化数字格式需要特定的标志。

Boost 语言环境要求您明确指定何时希望数字格式能够识别语言环境,这与 std::money_put 等最近的库决策更加一致。

【讨论】:

你将如何将它与 boost::lexical_cast 一起使用? boost::lexical_cast 使用全局语言环境。 boost::locale 库生成具有改进的数字格式行为(以及其他改进)的语言环境。因此,只需将 globale locale 设置为 boost locale,它 boost::lexical_cast 就会自动采用该行为。如果不清楚,请告诉我,我会举个例子。

以上是关于boost::lexical_cast<> 的语言环境不变保证的主要内容,如果未能解决你的问题,请参考以下文章

c++ boost lexical_cast double to string

boost lexical_cast <int> 检查

用boost::lexical_cast进行数值转换

一起学习Boost标准库--Boost.texical_cast&format库

boost::lexical_cast int 用零填充字符串

在 C++ 中使用 boost::lexical_cast 将双精度转换为字符串?