“按空格缩进处理”指对含换行符的文本逐行添加指定数量前导空格,保留原有换行与缩进结构,且不误缩进末行;需手动分段、判断行尾换行符、预生成缩进串,并注意空行保留与性能优化。

什么是“按空格缩进处理”?先确认需求边界
很多人看到这个说法第一反应是“把字符串每行开头加几个空格”,但实际在 C++ 工程中,这通常指:对一段含换行符的文本,将每一行(以 \n 分割)统一添加指定数量的前导空格,且不破坏原有缩进结构(即不是简单地在整串开头加空格)。
关键点在于:要保留原换行逻辑,只对每行内容做前缀插入,且不能把最后一行末尾的 \n 错误地多缩进一次。
用 std::string 手动分段 + 拼接最可控
标准库没有现成的 indent() 函数,最稳妥的方式是自己切分、逐行处理、再拼接。注意几个易错细节:
-
std::string::find('\n')返回std::string::npos时需终止循环,否则会无限重复最后一行 - 每次提取子串用
substr(start, end - start),避免越界(end可能为npos) - 行末是否带
\n要显式判断:若当前行以\n结尾,拼接时只加缩进 + 原内容;否则加缩进 + 原内容 +\n(最后一行无换行符) - 缩进字符串建议预生成一次,比如
std::string prefix(indent_width, ' '),避免反复构造
std::string indent_string(const std::string& s, size_t width) {
if (s.empty()) return s;
std::string result;
std::string prefix(width, ' ');
size_t start = 0;
size_t pos = s.find('\n');
while (pos != std::string::npos) {
result += prefix + s.substr(start, pos - start + 1); // +1 包含 \n
start = pos + 1;
pos = s.find('\n', start);
}
result += prefix + s.substr(start); // 最后一行不带 \n,不额外加
return result;
}
用 std::stringstream 按行读取更符合直觉,但要注意换行丢失风险
用 std::getline() 从 std::stringstream 中读取,逻辑清晰,但默认会吃掉 \n 且不保留空行——如果输入含连续 \n\n,中间的空行会被跳过。
- 若需保留空行,必须手动检查
ss.peek() == '\n'并补上 - 每次
getline()后,要显式追加\n(除非是最后一行) - 不推荐用于含大量空行或需要严格保持原始换行结构的场景
第三方库如 absl::StrCat 或 fmt::format 不直接支持,别硬套
有人试图用 fmt::format("{:>{}}", line, width) 做右对齐来“模拟缩进”,这是错的:{:>{}} 是右对齐填充,会把整行当一个单元塞进固定宽度,完全不是前缀添加。absl::StrCat 只是拼接工具,不提供按行处理逻辑。强行包装一层函数也可以,但没比手写 substr 版本更安全或更简洁。
真正容易被忽略的是:缩进操作常出现在日志打印、代码生成、配置输出等上下文中,这些场景往往要求零内存拷贝或流式处理。上面给的函数返回新 std::string,对大文本会触发多次分配。如果性能敏感,得改用输出迭代器或 std::ostream& 直接写入,而不是构造完整结果字符串。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











