双指针原地反转最健壮:先整体反转,再逐单词反转,全程操作原字符串,保留所有空白位置与类型。

直接用 std::stringstream 按空格分词再反转,无法处理连续空格、首尾空格和制表符等边界情况——它会把多个空格压缩成一个分隔,原始空白结构全丢。
为什么 std::stringstream 默认分词不保空白
因为 std::stringstream 使用空格类字符(' '、'\t'、'\n')作为分隔符,且自动跳过前导/连续分隔符。读取时只返回非空单词,原始位置、数量、类型全部丢失。
- 输入
" hello world\t"→ 只得到两个std::string:"hello"和"world" - 反转后拼接成
"world hello",但原字符串首尾和中间的空白全没了 - 如果需求是“单词反转但保留所有空白布局”,这条路走不通
用 std::istringstream + std::getline 手动按空格切分
改用 std::getline 配合自定义分隔符(比如单个空格),可以控制切分粒度,但要注意:它仍会把连续空格拆成多个空字符串,需额外过滤或保留。
std::vector<:string> tokens;
std::string s = " hello world\t";
std::istringstream iss(s);
std::string token;
// 每次读一个字符直到遇到 ' ',但 '\t' 不会被截断!
while (std::getline(iss, token, ' ')) {
tokens.push_back(token);
}
// tokens = {"", "", "hello", "", "", "", "world\t"} → 还得自己处理 '\t'</:string>
- 分隔符只能传单字符,
' '无法同时捕获'\t'或'\n' - 空字符串代表“前面有空格”,可用于还原空白数,但需区分是分隔产生的还是原内容
- 末尾制表符被吞进最后一个 token,要再做一次字符级扫描才能分离
真正健壮的做法:双指针原地反转(不依赖分词)
先整体反转,再逐个单词反转,全程操作 std::string&,不新增容器,也不丢失任何字符位置。
void reverseWords(std::string& s) {
// 第一步:整体反转
std::reverse(s.begin(), s.end());
// 第二步:对每个单词单独反转(识别连续非空格区间)
size_t start = 0;
while (start
- 输入
" hello world\t"→ 输出"\tworld hello ",完全保持空白原样 - 时间复杂度 O(n),空间 O(1),无内存分配,无额外 vector 或 stringstream 开销
- 注意:这个版本不清理空格,如果需求是“反转单词并只留单空格”,得额外加去重逻辑
真正难的不是反转,而是明确需求到底要不要保空白、要不要归一化、是否允许修改原串。很多人卡在 stringstream 上,是因为没想清楚:分词只是手段,而字符串布局才是契约。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











