C++ ostream填充出现末尾0问题求助:如何输出10个*?
问题分析与解决
首先咱们来拆解你代码里出现末尾0的原因,以及你误用width和fill的地方:
末尾0的成因
你的代码是:
ostream& write(ostream& os) { os << os.fill('*') << os.width(10); return os; }
这里的核心问题是:os.fill('*')和os.width(10)的返回值并不是你以为的ostream对象,而是它们修改前的旧值:
os.fill('*'):这个函数的作用是把流的填充字符设为*,但它的返回值是修改之前的填充字符(默认情况下是空格,不过如果你的环境里默认填充字符是\0,那它的ASCII值就是0——这就是你看到末尾0的来源)。os.width(10):这个函数的作用是设置下一次格式化输出的最小宽度为10,返回值是修改之前的宽度值(默认是0)。
而你用<<把这两个返回值直接插入到流里,实际执行流程是:
- 调用
os.fill('*'),返回旧填充字符(比如\0,对应输出0); - 调用
os.width(10),设置下一次输出宽度为10,返回旧宽度值0; - 因为
<<是左结合,先输出os.fill('*')的返回值,此时宽度已经被设为10,流会用新的填充字符*填充到10位,最终输出9个*加一个0(总长度10); - 接着输出
os.width(10)的返回值0,这就导致了你看到的末尾额外0。
如何正确实现输出10个*
你不需要把fill和width的返回值插入流,而是先调用它们设置格式,再输出内容;或者用更直观的方式构造字符串输出:
方法1:正确使用fill和width成员函数
先设置格式,再输出空字符串(width只对下一次格式化输出有效):
ostream& write(ostream& os) { os.fill('*'); // 设置填充字符,无需插入返回值 os.width(10); // 设置下一次输出宽度为10,无需插入返回值 os << ""; // 输出空字符串,自动用*填充到10位 return os; }
方法2:直接输出字符串(最直观)
这种方式不需要依赖流的格式化设置,代码更易懂:
#include <string> // 需要包含string头文件 ostream& write(ostream& os) { os << std::string(10, '*'); return os; }
方法3:使用操纵符(推荐)
C++的iomanip库提供了setfill和setw操纵符,用法更简洁,还能避免成员函数返回值的坑:
#include <iomanip> // 需要包含iomanip头文件 ostream& write(ostream& os) { os << std::setfill('*') << std::setw(10) << ""; return os; }
注意:setw仅对下一次输出有效,而setfill会持续生效,直到你再次修改它。
内容的提问来源于stack exchange,提问作者Devin
相关产品推荐
相关产品推荐

