如何移除std::locale的numpunct分组并保留其他本地化格式
解决std::locale移除千位分隔符但保留其他区域特性的问题
你的问题出在自定义numpunct直接继承自std::numpunct<char>基类,这会导致除了do_grouping之外的其他格式特性(比如小数分隔符)都使用默认"C"区域的设置,而非目标区域(sk_SK)的配置。正确的做法是基于原区域的numpunct facet进行修改,仅覆盖分组规则,其他特性保留原区域的行为。
修正后的代码示例
#include <iostream> #include <locale> #include <sstream> // 自定义numpunct:仅禁用千位分隔符,保留原区域的其他格式特性 struct no_separator : public std::numpunct<char> { explicit no_separator(const std::numpunct<char>& original) : original_(original) {} protected: // 重写分组规则:返回"\0"表示禁用千位分隔符 virtual string_type do_grouping() const override { return "\0"; } // 以下方法全部委托给原区域的numpunct,保留原有特性 virtual char_type do_decimal_point() const override { return original_.decimal_point(); } virtual char_type do_thousands_sep() const override { return original_.thousands_sep(); } virtual string_type do_truename() const override { return original_.truename(); } virtual string_type do_falsename() const override { return original_.falsename(); } private: const std::numpunct<char>& original_; }; int main() { std::cout.precision(8); std::cout.width(12); std::cout << "Test \"C\": " << 1234.5678 << std::endl; // 输出:1234.5678 std::locale skSKLocale("sk_SK"); std::cout.imbue(skSKLocale); std::cout << "Test skSK: " << 1234.5678 << std::endl; // 输出:1 234,5678 // 获取原区域的numpunct facet实例 const auto& original_numpunct = std::use_facet<std::numpunct<char>>(skSKLocale); // 创建新区域:基于sk_SK,替换numpunct为自定义版本 std::locale no_thousands_locale(skSKLocale, new no_separator(original_numpunct)); std::cout.imbue(no_thousands_locale); std::cout << "Test no thousands: " << 1234.5678 << std::endl; // 输出:1234,5678(符合预期) }
关键说明
- 委托原facet:自定义
no_separator通过构造函数接收原区域的numpunct引用,所有未重写的方法都直接调用原facet的对应方法,确保小数分隔符等特性保持原区域的设置。 - 仅修改分组规则:只重写
do_grouping方法,返回"\0"表示不进行任何分组(即禁用千位分隔符)。 - 正确创建新locale:通过
std::locale的构造函数,基于原区域替换指定的facet,而非完全替换所有numpunct特性。
内容的提问来源于stack exchange,提问作者byKiVi
相关产品推荐
相关产品推荐

