
用 std::setw 和 std::setfill 做流式填充
这是最常用、最轻量的左/右填充方式,适用于输出到 std::cout 或字符串流。它不修改原字符串,只在格式化输出时生效。
关键点:必须搭配 std::left 或 std::right(默认右对齐),且 std::setw 只对**下一个输出项**有效,不可复用。
-
std::right+std::setw(n)→ 右对齐,左侧补空格(即“左填充”语义) -
std::left+std::setw(n)→ 左对齐,右侧补空格(即“右填充”语义) -
std::setfill(c)必须在std::setw之前或同一行设置,否则无效
#include#include #include std::string s = "abc"; std::ostringstream oss;
oss << std::right << std::setfill('0') << std::setw(6) << s; // 结果: "000abc"(左填充0)
oss.str(""); // 清空 oss << std::left << std::setfill('*') << std::setw(6) << s; // 结果: "abc**"(右填充)
用 std::string::insert 或 std::string::append 手动构造填充
当需要真正生成新字符串(比如存入容器、传参、做计算),不能依赖流格式化时,就得手动拼接。这种方式可控性强,但要注意边界:如果原字符串长度 ≥ 目标宽度,多数实现会直接返回原串(不截断)。
- 左填充(在开头加字符):用
s.insert(0, count, c) - 右填充(在末尾加字符):用
s.append(count, c) -
count = std::max(0, target_len - static_cast,避免负数导致未定义行为(s.length()))
#include#include std::string pad_left(const std::string& s, size_t target_len, char c = ' ') { if (s.length() >= target_len) return s; return std::string(target_len - s.length(), c) + s; }
std::string pad_right(const std::string& s, size_t target_len, char c = ' ') { if (s.length() >= target_len) return s; return s + std::string(target_len - s.length(), c); }
注意 std::string::resize 的陷阱:它会截断或填充,但方向固定
std::string::resize(n, c) 看起来很适合填充,但它只支持**右填充**(即在末尾补字符),且当 n 时会**无条件截断**——这和多数“填充函数”预期不符(通常期望保持原内容不变)。
立即学习“C++免费学习笔记(深入)”;
- 想做右填充且允许截断?可以用,但要确认业务能接受丢失数据
- 想做左填充?
resize完全不适用,强行用需配合insert - 多字节字符(如 UTF-8 中文)?
resize按字节操作,可能破坏编码,慎用
std::string s = "你好"; s.resize(10, '*'); // 若原始是UTF-8,长度为6字节,resize(10)会在末尾加4个'*' // 但若写成 s.resize(5, '*'),会截掉至少1个中文字符,结果不可控
C++20 起可用 std::format,但要注意兼容性和宽度单位
std::format 提供类似 Python 的格式语法,支持 {:>8}(右对齐宽8)、{:*(左对齐、*填充、宽8)。但它对“宽度”的理解是**字符数(code points)**,不是字节数;而 std::string 是字节容器,遇到 UTF-8 多字节字符时,std::format 会尝试解码,但标准库实现质量参差不齐。
- 纯 ASCII 场景下最简洁:
std::format("{:0>6}", "abc")→"000abc" - MSVC 19.3x+ 和 GCC 13+ 支持较好;Clang 15+ 需启用
-std=c++20并确认 libstdc++/libc++ 版本 - 不要假设
std::format在所有平台都返回 UTF-8 字符串——它返回std::string,但填充逻辑依赖内部 Unicode 处理
实际项目中,如果还没强制要求 C++20,老老实实用 std::stringstream 或手动拼接更稳妥。











