正确做法是用双指针定位每个单词边界(连续非空格字符序列),再对每个单词区间调用std::reverse;需处理首尾及连续空格,原地修改保留空格位置,避免使用split丢失空格信息。

用 std::reverse 配合双指针找单词边界
直接对整个字符串调用 std::reverse 会把整个串倒过来,不是“每个单词反转”。正确做法是:先定位每个单词的起始和结束位置(跳过空格),再对每个单词内部单独调用 std::reverse。
关键点在于识别单词——连续非空格字符序列。空格可能是多个、也可能在首尾,所以不能简单按 ' ' 拆分。
- 用两个索引
start和end扫描:外层循环找到每个单词开头,内层扩展到单词结尾 - 每次找到一个单词区间
[start, end)后,调用std::reverse(s.begin() + start, s.begin() + end) - 注意
std::reverse的迭代器是左闭右开区间,别写成...+end + 1 - 字符串末尾无空格时,容易漏掉最后一个单词,需在循环结束后补一次处理
遇到连续空格或首尾空格怎么办
原地修改时,空格位置必须保留,只翻转字母/数字等非空格字符组成的段。如果用 std::istringstream 拆词再拼接,会丢失所有原始空格信息(包括数量和位置),结果不符合“字符串中每一个单词反转”的语义。
- 必须原地扫描,不依赖
std::string::find_first_of或split类操作 - 判断字符是否为空格,用
std::isspace(static_cast<unsigned char>(c))</unsigned>更安全(避免char为负时 UB) - 但日常 ASCII 场景下,直接比较
c == ' '足够,且更快 - 首尾空格不参与任何反转,仅作为单词分隔符存在
C++20 起可用 std::ranges::reverse 简化写法吗
可以,但要注意子范围构造方式。C++20 的 std::ranges::reverse 接受一个 std::ranges::borrowed_range,不能直接传两个迭代器;得先用 std::ranges::subrange 或容器视图包装。
- 推荐写法:
std::ranges::reverse(std::ranges::subrange{it_start, it_end}) - 但相比传统
std::reverse(it_start, it_end),并无实质优势,反而增加理解成本 - 若项目已全面启用 C++20 且使用
std::string_view做输入,可考虑配合std::views::split,但会再次丢失空格——所以仍不适用于本题要求
常见错误:把 reverse 作用在 std::string 迭代器上却忘了更新索引
最容易出错的是:在翻转完一个单词后,没把扫描位置设到下一个空格之后,导致重复处理或跳过单词。例如在 "hello world"(两个空格)中,从索引 5 开始找下一个非空格,得跳过两个空格到索引 7,而不是只加 1。
- 外层循环每次推进到
end + 1,不是end - 内层找单词起点时,要跳过所有空格,直到
start - 调试时可在循环内加
std::cout 快速验证区间是否正确 - 空字符串或全空格字符串要能安全退出,避免
start越界
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











