前言
字符串处理是 C++ 编程中的基础技能,而单词翻转则是考察字符操作逻辑的经典题目。这道题不仅要求理解输入输出的格式,还涉及多种反转策略的权衡。本文将通过三种不同的实现方式——手动遍历、双指针交换以及标准库函数,深入剖析其背后的思路与优劣。
题目描述
B2122 单词翻转
小明写单词时习惯反着写,例如 hello 写成 olleh。现在给定一个包含多个单词的句子,要求将每个单词复原,并按行输出。
输入格式
一行字符串,单词间以空格分隔。
输出格式
每个单词占一行。
样例
输入:
olleh dlrow
输出:
hello
world
方案一:手动遍历字符
这是最直观的思路。利用 cin >> s 的特性,它会自动按空格读取单词,我们只需对读入的字符串进行逆序输出即可。
代码实现
#include <iostream>
#include <string>
using namespace std;
int main() {
string s;
while (cin >> s) {
for (int i = s.size() - 1; i >= 0; i--) {
cout << s[i];
}
cout << endl;
}
return 0;
}
思路解析
这里利用了 cin 流提取符跳过空白符的特性。循环从字符串末尾向前遍历,逐个打印字符。这种方式不需要修改原字符串,直接输出结果,内存开销极小。不过,如果后续需要保留反转后的字符串,这种只读不写的模式就不太适用了。
方案二:双指针交换
如果想原地修改字符串,可以使用双指针法。定义左右两个索引,分别指向首尾,交换后向中间靠拢。
代码实现
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main() {
string str;
while (cin >> str) {
int left = 0;
int right = str.size() - 1;
while (left < right) {
swap(str[left], str[right]);
left++;
right--;
}
cout << str << endl;
}
return 0;
}
思路解析
相比第一种方案,这种方法实际修改了字符串内容。swap 函数通常由编译器优化得很高效。注意边界条件,当 left 等于 right 时(奇数长度字符串的中间字符),无需交换,循环终止条件设为 < 而非 <= 是关键。
方案三:使用 std::reverse
C++ 标准库提供了现成的工具,既简洁又不易出错。
代码实现
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main() {
string str;
while (cin >> str) {
reverse(str.begin(), str.end());
cout << str << endl;
}
return 0;
}
思路解析
std::reverse 接受迭代器范围作为参数。对于初学者来说,这能极大减少手写循环带来的 bug 风险。在实际工程中,除非有特殊的性能限制或学习需求,否则优先推荐使用标准库算法。
总结与对比
- 手动遍历:适合仅需输出结果的场景,逻辑简单,但无法复用反转后的数据。
- 双指针:适合需要原地修改的场景,体现了算法思想,但代码量稍多。
- 标准库:开发效率最高,可读性最强,推荐日常使用。
掌握这三种写法,能让你在面对字符串处理问题时更加游刃有余。


