最稳妥方案是用std::istringstream按空白拆分单词存入vector,再逐个反转单词内部字符,最后单空格拼接;它自动跳过所有冗余空白,避免越界与空格处理错误,适合ASCII场景。

用 std::istringstream 拆分再拼接是最稳的方案
直接操作原字符串容易越界或漏空格,尤其当输入含多个连续空格、首尾空格时。std::istringstream 自动跳过冗余空白,按单词提取,语义清晰且无边界风险。
- 先用
std::istringstream读出每个单词,存入std::vector<:string></:string> - 对每个单词调用
std::reverse(注意是std::reverse(word.begin(), word.end()),不是整个 vector) - 拼接时手动补空格:每加一个单词,若非首个,则前置一个空格
std::string s = "hello world test";
std::istringstream iss(s);
std::vector<std::string> words;
std::string word;
while (iss >> word) {
std::reverse(word.begin(), word.end());
words.push_back(word);
}
std::string result;
for (size_t i = 0; i < words.size(); ++i) {
if (i > 0) result += " ";
result += words[i];
}
想原地翻转?必须自己处理空格边界
原地算法节省空间,但逻辑变重:要识别单词起止索引,且不能破坏空格位置。标准库没提供“按空格切片并原地反转”的现成函数,得手写双指针。
- 先用
std::reverse反转整个字符串,让单词顺序颠倒、内部也颠倒 - 再遍历一遍,对每个连续非空格子串再次
std::reverse—— 这样单词内部恢复正序,整体顺序却已翻转(不符合题意) - 所以真要原地且保持单词顺序,只能扫两遍:第一遍标出所有单词区间,第二遍对每个区间单独反转
注意:std::string::erase 和 insert 会触发内存重分配,不算真正“原地”;纯 in-place 必须用 swap 或 std::reverse 配合下标。
遇到 Unicode(比如中文、emoji)怎么办
C++ 标准库的 std::string 是字节序列,std::reverse 对 UTF-8 字符串直接翻转会破坏编码——比如把 "好"(UTF-8 三字节)翻成乱码。
立即学习“C++免费学习笔记(深入)”;
- 如果输入确定是 ASCII 单字节字符,放心用
std::reverse - 若需支持多字节字符,必须先按 Unicode 码点切分,例如用
std::wstring+std::locale,或引入 ICU / utf8cpp 库 - 常见错误:用
for (auto& c : word)遍历时以为c是字符,实际是字节;应改用utf8::next()类接口
性能敏感场景别用 + 拼接字符串
频繁 result += word 在旧编译器可能触发多次内存重分配,尤其是单词数量多时。
- 提前用
words.size()和平均长度预估容量:result.reserve(total_len) - 更稳妥:用
std::ostringstream替代字符串拼接,流内部通常有缓冲优化 - 极端情况(如百万单词),考虑输出到
std::vector<char></char>再构造 string,避免流开销
空格处理细节最容易被忽略:题目说“保持顺序”,指的是单词在句中的出现顺序不变,而非空格数量和位置不变——所以用 >>> 丢弃多余空格是符合要求的,不必费力保留原始空白布局。


















