文章目录
- 💯前言
- 💯题目描述
- 输入格式
- 输出格式
- 样例 #1
- 样例输入 #1
- 样例输出 #1
- 💯一、我的做法
- 代码实现:
- 代码解析
- 思路分析
- 💯二、老师的第一种做法
- 代码实现:
- 代码解析
- 思路分析
- 💯三、C++ `reverse` 函数介绍
- `reverse` 函数原型:
- 示例:
- 优点
- 💯四、老师的第二种做法:使用 `reverse` 函数
- 代码实现:
- 代码解析
- 思路分析
- 💯五、对比分析
- 💯六、拓展
- 💯小结
- 最开始的解法不通过
- 老师优化后通过
💯前言
- 在计算机科学中,字符串处理是一个非常基础且常见的任务。本题主要围绕如何将一个句子中的每个单词反转来进行练习。这个问题不仅考察了对字符串操作的理解,还涉及了不同的解决方法。在本篇文章中,我们将详细探讨我自己的做法、老师提出的两种做法,并深入讲解C++中
reverse
函数的使用,最后通过对比和拓展分析这些方法的优缺点。
C++ 参考手册
💯题目描述
B2122 单词翻转
小明同学写单词的时候喜欢反着写,比如 hello
他会写成 olleh
。给出小明同学写的一个句子,请你将所有的单词复原。
输入格式
共一行,一个字符串表示句子,单词之间以空格分隔。
输出格式
每个单词一行。
样例 #1
样例输入 #1
olleh dlrow
样例输出 #1
hello
world
💯一、我的做法
代码实现:
#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;
}
代码解析
在这个实现中,我选择了通过手动反转每个单词的字符来恢复正确的单词顺序。
-
变量声明:
string s;
:声明一个字符串变量s
用于存储从输入中读取的每个单词。
-
读取输入:
while(cin >> s)
:使用cin >> s
读取一个单词,直到没有更多输入。
-
反转每个单词:
for(int i = s.size() - 1; i >= 0; i--)
:我们使用一个从单词末尾到开头的for
循环,通过访问每个字符并逆序输出,来实现反转操作。
-
输出每个单词:
cout << s[i];
:逐个输出反转后的字符。
-
换行:
- 每个单词输出后,使用
cout << endl;
换行,确保每个单词占一行。
- 每个单词输出后,使用
思路分析
这段代码通过遍历每个字符并从末尾到开头进行输出来实现反转。通过这种手动操作字符的方式,能够准确地完成任务。它的优点是直接且易于理解,但缺点是代码稍显冗长,且没有利用C++标准库提供的便捷工具。
💯二、老师的第一种做法
老师给出的第一种做法是通过手动交换字符串中的字符来反转单词。下面是老师的代码实现:
代码实现:
#include <iostream>
#include <cstring>
using namespace std;int main()
{string str;while(cin >> str){int left = 0;int right = str.size() - 1;while(left < right){char tmp = str[left];str[left] = str[right];str[right] = tmp;left++;right--;}cout << str << endl;}return 0;
}
代码解析
老师的做法同样采用了字符交换的方式来反转每个单词。其关键点在于通过两个指针从字符串的两端向中间移动,交换字符,直到完成反转。
-
初始化两个指针:
int left = 0; int right = str.size() - 1;
:left
和right
分别是指向字符串开始和结束的两个指针。
-
交换字符:
char tmp = str[left]; str[left] = str[right]; str[right] = tmp;
:通过一个临时变量tmp
来交换str[left]
和str[right]
。
-
逐步移动指针:
left++
和right--
:交换后,left
指针向右移动,right
指针向左移动,逐步将字符串反转。
-
输出反转后的字符串:
cout << str << endl;
:输出反转后的单词。
思路分析
老师的做法通过交换字符来反转字符串,使用了双指针的技巧,这种方法比我的做法更具效率,因为它只需要一次遍历,每次只交换两个字符。相比手动逐个输出字符,这种方法更符合常见的反转思路,代码更简洁。
💯三、C++ reverse
函数介绍
在C++标准库中,提供了一个名为 reverse
的函数,它可以轻松地反转一个容器(例如字符串、数组等)的元素顺序。该函数位于 <algorithm>
头文件中,使用时非常方便。
reverse
函数原型:
void reverse(BidirectionalIterator first, BidirectionalIterator last);
- first:指向待反转区间的起始元素的迭代器。
- last:指向待反转区间的结束元素的迭代器。
该函数会反转区间 [first, last)
中的元素。
示例:
string s = "abcd";
reverse(s.begin(), s.end());
cout << s << endl; // 输出 "dcba"
优点
- 简洁:C++
reverse
函数将反转操作封装得非常简洁。只需调用一次reverse
,就能完成字符串或数组的反转,代码更加清晰易懂。 - 高效:
reverse
内部实现通常采用类似于双指针交换的方式,性能非常高。
💯四、老师的第二种做法:使用 reverse
函数
老师的第二种做法直接利用了 C++ STL 中的 reverse
函数,这使得反转操作变得更加简便。
代码实现:
#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;
}
代码解析
这段代码通过 reverse
函数反转字符串:
-
使用
reverse
函数:reverse(str.begin(), str.end());
:直接使用reverse
函数来反转字符串str
。
-
输出反转后的字符串:
cout << str << endl;
:输出每个反转后的单词,并换行。
思路分析
这种做法通过使用 C++ STL 中的现成函数来简化代码。reverse
函数提供了高效且简洁的反转操作,比手动交换字符或逐个输出字符的方法要简单得多。
💯五、对比分析
-
我的做法:
- 优点:代码简单,容易理解,适用于初学者。
- 缺点:冗长,效率较低,特别是手动反转每个字符时,不够高效。
-
老师的第一种做法:
- 优点:通过双指针交换字符,比手动输出字符更高效。
- 缺点:代码较为复杂,理解起来可能稍微困难。
-
老师的第二种做法:
- 优点:使用
reverse
函数,代码最简洁,符合C++的标准库优势,效率高。 - 缺点:可能需要对
reverse
函数有一定的了解。
- 优点:使用
💯六、拓展
除了 reverse
函数外,我们还可以用其他方式来处理字符串或数组的反转操作:
- 利用栈:将字符压入栈中,然后从栈中弹出字符来实现反转。
- 递归:通过递归函数逐步将字符串或数组的字符进行反转。
💯小结
通过对比不同的做法,我们可以看到,C++提供了多种有效的反转策略。通过手动字符交换、使用 reverse
函数,甚至使用 STL 容器的其他方法,我们可以灵活地选择最适合问题需求的解决方案。在实际开发中,选择合适的工具和方法,不仅能提高代码的可读性,还能提高程序的效率。
最开始的解法不通过
#include <iostream>
#include <string>
using namespace std;int main()
{string s;getline(cin, s);int i = 0;int index = 0;for(i = 0; i < s.size(); i++){if(s[i] == ' '){for(int j = i - 1; j >= index; j--)cout << s[j];cout << endl;index = i + 1; }else if(i == s.size() - 1){for(int j = i; j >= index; j--)cout << s[j];cout << endl;} } return 0;
}
老师优化后通过
#include <iostream>
#include <string>
using namespace std;int main()
{string s;getline(cin, s);int i = 0;int index = 0;for (i = 0; i < s.size() - 1; i++){if (s[i] == ' '){for (int j = i - 1; j >= index; j--){cout << s[j];}cout << endl;index = i + 1;}else if (i == s.size() - 2){for (int j = i; j >= index; j--){cout << s[j];}cout << endl;}}return 0;
}