自定义String_numput facet无法写入字符串,请求技术排查
问题分析与解决方案
你的代码有几个关键问题导致字符串没有被写入,我逐一解释并给出修复方案:
1. 字符串没有足够的可写空间,写入位置无效
你初始化的s是空字符串,s.begin() + pos(当pos=0时)指向的是字符串的末尾(空字符串的begin()和end()是同一个迭代器)。std::num_put::put只是将字符写入迭代器指向的内存位置,但它不会自动扩展字符串的空间——直接往空字符串的迭代器位置写入会触发未定义行为,自然不会有内容被写入到字符串里。
2. 未利用put的返回值跟踪写入位置
num_put::put会返回写入完成后的迭代器,但你没有用这个返回值来更新字符串的状态。即使你预先分配了空间,也需要通过返回的迭代器确认实际写入的长度,避免字符串里残留未初始化的内容。
3. 参数类型不匹配导致数据截断
你的test函数参数是long i,但调用时传入的是4567.9(double类型),这会触发隐式转换,小数部分被直接截断成4567,这显然不是你想要的浮点数值输出效果。
修复后的代码示例
方案1:使用std::back_inserter自动扩展字符串
这是最简便的方式,back_inserter会把写入操作转换成string::push_back,自动为字符串分配空间:
#include <iostream> #include <string> #include <locale> #include <iterator> template<typename C> class String_numput : public std::num_put<C, typename std::basic_string<C>::iterator> { public: String_numput() : std::num_put<C, typename std::basic_string<C>::iterator>{1} {} }; using namespace std; // 修改参数类型为double以支持浮点输入 void test(double i, string& s) { String_numput<char> f; // 使用back_inserter自动向字符串末尾添加字符 auto end_iter = f.put(back_inserter(s), cout, ' ', i); cout << s << endl; } int main() { string s {}; test(4567.9, s); cout << "completed" << endl; }
方案2:预先分配空间并手动管理写入位置
如果你需要指定写入的起始位置,可以预先resize字符串到足够的长度,再用返回的迭代器截断到实际写入的长度:
#include <iostream> #include <string> #include <locale> template<typename C> class String_numput : public std::num_put<C, typename std::basic_string<C>::iterator> { public: String_numput() : std::num_put<C, typename std::basic_string<C>::iterator>{1} {} }; using namespace std; void test(double i, string& s, int pos) { String_numput<char> f; // 预先分配足够的空间(这里假设最多需要20个字符) if (s.size() < pos + 20) { s.resize(pos + 20); } // 从指定位置写入 auto end_iter = f.put(s.begin() + pos, cout, ' ', i); // 截断字符串到实际写入的末尾 s.resize(end_iter - s.begin()); cout << s << endl; } int main() { string s {}; test(4567.9, s, 0); cout << "completed" << endl; }
补充说明:你在String_numput构造函数中传入1作为引用计数的做法是正确的,这表示该facet不会被locale管理,生命周期由你手动控制,这部分没有问题。
内容的提问来源于stack exchange,提问作者SSteven
相关产品推荐
相关产品推荐

