yaml-cpp为何给数字添加千位分隔符?如何禁用该功能?
问题描述
测试代码:
std::cout << "std::cout for 2112 = " << 2112 << '\n'; std::stringstream ss; ss << 2112; std::cout << "std::stringstream for 2112 = " << ss.str() << '\n'; YAML::Emitter out; out << 2112; std::cout << "Emitter for 2112 = " << out.c_str() << '\n';
运行输出:
std::cout for 2112 = 2112 std::stringstream for 2112 = 2,112 Emitter for 2112 = 2,112
推测YAML::Emitter基于std::stringstream实现,千位分隔符由此产生。尝试注入std::locale{"C"}但无法让yaml-cpp生效;若先将数字转为字符串再传入Emitter,会丢失yaml-cpp便捷的operator<<重载,想找更简便的方法避免YAML字符串中出现千位分隔符。
另外,YAML::Emitter支持接收std::ostream作为底层流,但给该流设置locale为"C"并未解决问题;甚至用stringstream构造Emitter时,Emitter完全无法生成文本。
解决方法
1. 全局设置C locale
在程序启动时全局配置C locale,所有依赖locale的流操作都会使用无千位分隔符的格式,yaml-cpp的Emitter也会遵循该设置:
#include <locale> #include "yaml-cpp/emitter.h" int main() { std::locale::global(std::locale("C")); YAML::Emitter out; out << 2112; std::cout << "Emitter for 2112 = " << out.c_str() << '\n'; // 输出2112 return 0; }
这种方式简单直接,适合整个程序需要统一使用C locale的场景。
2. 给底层流设置locale并手动刷新
yaml-cpp的Emitter内部可能缓存数据,直接传入带C locale的stringstream后,需要手动调用flush()确保内容写入底层流:
#include <sstream> #include <locale> #include "yaml-cpp/emitter.h" int main() { std::stringstream ss; ss.imbue(std::locale("C")); YAML::Emitter out(ss); out << 2112; out.flush(); // 必须手动刷新,否则底层流无数据 std::cout << "Emitter for 2112 = " << ss.str() << '\n'; // 输出2112 return 0; }
3. 自定义流缓冲注入C locale
如果不想全局修改locale,可以创建带有C locale的流缓冲,再关联到Emitter的输出流:
#include <streambuf> #include <locale> #include "yaml-cpp/emitter.h" int main() { std::stringbuf buf; buf.pubimbue(std::locale("C")); std::ostream os(&buf); YAML::Emitter out(os); out << 2112; out.flush(); std::cout << "Emitter for 2112 = " << buf.str() << '\n'; // 输出2112 return 0; }
关键说明
yaml-cpp的Emitter处理数字时,会遵循当前全局locale或内部流的locale格式。直接给传入的ostream设置locale无效,大概率是因为Emitter内部写入时覆盖了locale设置,或是未同步流的locale配置。全局设置C locale是最稳妥的方案,除非有其他模块依赖系统默认locale。
内容的提问来源于stack exchange,提问作者Tom
相关产品推荐
相关产品推荐

