题目:将一句话的单词进行倒置,标点不倒置。比如 I like beijing. 经过函数后变为:beijing. like I
输入描述:
每个测试输入包含1个测试用例: I like beijing. 输入用例长度不超过100
输出描述:
依次输出倒置之后的字符串,以空格分割
示例:
#include<stdio.h>
#include<string.h>
void reverse(char* left, char* right)
{
while (left < right)
{
char tmp = *left;
*left = *right;
*right = tmp;
left++;
right--;
}
}
int main()
{
char arr[100] = { 0 };
gets_s(arr);
int len = strlen(arr);
char* left = arr;
char* right = arr + len - 1;
reverse(left, right);
char* start = arr;
char* end = arr;
while (*end != '\0')
{
while (*end != ' '&& *end!='\0')
{
end++;
}
reverse(start, end - 1);
start = end + 1;
if (*end != '\0')
{
end++;
}
}
printf("%s\n", arr);
return 0;
}
情况来看就是这么个情况,仔细看看题就会发现,哎不对诶,这跟咱们之前的那些字符串逆序不一样诶。如果是之前写过的字符串逆序,整个倒个个儿得到的应该是.gnijieb ekil I相当于将每个字母都看作独立的单元了,但是题目要求显然不是,它是要求我们逆序,但是要求实现的效果是整个单词黏在一起的样子。我们要实现这个效果其实也不难想,只需要在上面整个字符串逆序之后再对每个单词进行逆序就好啦!
简单概括一下就是:先整体逆序,再局部逆序。
那对于最后这个“ . ”是怎么处理的呢?其实仔细观察就会发现端倪,在我们对整个字符串进行逆序之后,这时第一个单词为“ .gnijieb “,那么动动聪明的小脑瓜,没错,就是把它进行逆序的结果!这样一切就解释的通啦,让我们来看看代码怎么写吧!
因为输入用例中长度不超过100,所以我们可以定义一个数组arr,元素为100个,每个元素类型为char,即为char arr[100]={0},暂时先放入0。
接着我们往数组里面放入字符串,然而字符串里面的每个单词之间都是有空格的,这时的scanf就无法将有空格的数据输入了,因为它遇到空格就会停下,不再读取后面的内容。所以我们选用gets来进行数据的输入。(在牛客网上面使用gets是对的,然而在vs上面可能就需要gets_s才能够编译运行)
当然如果非要使用scanf其实也是有办法的(就是很怪)意思就是一直往后读,直到遇到\n停止,不如直接使用gets更加方便。
接下来我们来实现逆序:
逆序整个字符串的时候需要知道第一个字符与最后一个字符的位置,逆序每个单词的时候需要知道这个单词第一个字符与最后一个字符的位置,那就会发现,诶好像是一样的诶,我们就可以把这两个逆序合并成一个过程来实现
对于一个字符串来说,我们想要知道第一个字符和最后一个字符的位置,就用两个指针,其中left指向第一个字符,right指向最后一个字符。那么当然啦第一个字符的地址就是数组名嘛,但是最后一个字符的位置可不是100-1哦!因为虽然定义arr数组有100个元素,可是这100个并不是都放了我们输入进去的字符,还有好多都是0嘞,因此需要使用strlen来求出字符串的长度,不要忘记头文件加上string.h哦
同时调用逆序函数reverse(left,right)即为将left与right之间的字符串进行逆序
下面我们来实现这个reverse函数
因为仅仅是将字符串逆序,并不需要传参,所以函数返回值类型为void;同时我们传进去的参数为两个指针,那么这时函数的参数也应该为两个char*类型的指针
使用while循环,当左侧地址小于右侧地址时,将两个指针指向的内容进行交换,交换完后两个指针同时向中间靠近,使用left++,right—
接着我们可以对每个单词进行逆序,首先需要将这个单词的起始位置记住,单词的起始位置其实就是数组首元素地址,定义char*类型的指针end等于数组名,单词的最后一个字符就是空格的前一个位置,我们也先让他等于数组首元素地址arr,同时运用一个while循环,当指针指向的字符为“ ”时停下,再减一,接着同时将开始和结束的指针传入reverse函数进行字符逆序
但是问题来了,刚刚写的这几行代码其实都只是逆序了第一个单词,我们要想逆序所有单词,就需要把他们放在一个while循环中。当第一个单词reverse进行字符串逆序后,我们需要让start指针向后移动,首先end指针目前指向的是第一个空格,当对第二个单词进行字符串逆序的时候,首字母地址就是空格后面的第一个字符鸭,因此重新定义start=end+1,同样指针end也应该向后走,不能仅仅停留在一个空格里面,所以end++!我们要让这个指针一直往后走,那么我们大的循环条件即为指针指向的不是最后一个字符\0
然而这个代码仍然存在问题:对每个单词进行逆序的时候,最后一个单词该怎么办?最后一个单词后面不再是空格而是\0,这时我们只需要在while循环里加上一个条件&&,并且end指针指向的不是\0,同时最后的end++,不能随意++,如果end指针指向的是最后一个字符,这时显然已经不再需要++,因此需要在++之前加上一个条件判断,如果end指针指向的内容不是\0再进行++,这样就完成了局部字符串逆序,最终将字符串打印出来即可