前言:题目来自牛客网 倒置字符串
第一种方法
基本思路:
第一种方法就是先逆置整个字符串I like beijing.逆置之后就是 .gnijieb ekil I
然后再对每一组单词进行逆置就变成了 .beijing like I
接下来我们再来谈一下,具体是怎么实现的
首先我们要先逆置整个字符串就需要两个下标,一个指向I,一个指向结尾也就是 . 首元素和尾元素交换完之后,下标分别进行++和–,再来交换下一组元素,直到左下标大于右下标的时候(标志着交换已经全部完成了)结束循环
这里我们把这部分封装成一个函数来实现,(因为在逆置单词的时候也会用到这个方法)下面会给出完整的代码
void reverse(char* left, char* right)
{
assert(left && right);
while (left <= right)
{
int ret = *left;
*left = *right;
*right = ret;
left++;
right--;
}
}
接下来我们要考虑的就是如何逆置一个单词了
我们同样可以参考上面的方法,给出两个指针,一个作为单词的开始标志,一个做为单词结束标志,如何再去调用上面的函数,这样就完成了我题目的要求,同样我们要考虑的是什么时候循环结束,我们仔细观察一下,当结尾遇到空格的时候就要停下来,完成一个单词的逆置,当遇到\0的时候,标志着整个逆置单词也完成了
所以这时候我们就需要用到嵌套循环结构来完成这一过程
下面第一种方法的具体实现
#include <stdio.h>
#include <string.h>
#include <assert.h>
//先逆整个数组,再逆序单词
void reverse(char* left, char* right)
{
assert(left && right);
while (left <= right)
{
int ret = *left;
*left = *right;
*right = ret;
left++;
right--;
}
}
int main()
{
char arr[101] = { 0 };
gets(arr);
int len = (int)strlen(arr) - 1;
先逆序整个字符串
reverse(arr, arr+len);
printf("%s\n", arr);
char* pc = arr;
// 逆置单词
while (*pc)
{
char* start = pc;
char* end = pc;
while (*end != ' ' && *end != '\0')
{
end++;
}
reverse(start, end-1);//这里要end-1,因为你遇到空格停下来,如果不-1的话,就是把空格传过去了
//这里要判断一下是不是到了结尾
if (*end != '\0')
pc = end + 1;
else
pc = end;//如果end遇到\0,标志着单词逆置已经全部完成
}
printf("%s\n", arr);
return 0;
}
第二种方法
然后第二种方法就是先逆置单词再逆置整个字符串,和第一种方法是一样的,这里我就不做过多的介绍了,直接给出大家代码看一下就OK了
#include <stdio.h>
#include <string.h>
#include <assert.h>
//先逆序单词,再逆序整个数组
void reverse(char* left, char* right)
{
assert(left && right);
while (left < right)
{
char ret = *left;
*left = *right;
*right = ret;
left++;
right--;
}
}
int main()
{
char arr[101] = { 0 };
gets(arr);
char* pc = arr;
//逆置单词
while (*pc)
{
char* start = pc;
char* end = pc;
while (*end != ' ' && *end != '\0')
{
end++;
}
reverse(start, end-1);//逆序单词
if (*end != '\0')
pc = end+1;
else
pc = end;//如果end遇到\0,标志着单词逆置已经全部完成
}
//逆序整个字符串
int len = strlen(arr) - 1;
reverse(arr, arr + len);
printf("%s\n", arr);
return 0;
}
第三种方法
第三种方法也是大部分人的想法,就是再创建一个大小相同的数组,然后后向前遍历整字符串数组,遇到空格就要遇到空格以后的内容放到新数组当中,然后打印新数组就行了
不过大家要注意的是,这种方法是无法将第一个 I 放进新数组当中去的,因为我们是遇到空格之后,把空格以后的内容放进新数组当中,但是第一个单词之前是没有空间的,也就没法遇到空格,就没法将其放到新数组当中
所以我们还需要一个从前往后遍历一次数组,不过要在遇到第一个空格之后就停下来
第三种方法代码
#include <stdio.h>
#include <string.h>
int main()
{
char arr[101] = { 0 };
char ch[101] = { 0 };
int start = 0;
gets(arr);
int len = strlen(arr);
int i = 0;
int j = 0;
for (i = len; i >= 0; i--)
{
if (arr[i] == ' ')
{
for (j = i + 1; arr[j] != ' ' && arr[j] != '\0'; j++)
{
ch[start] = arr[j];
start++;
}
ch[start] = ' ';//因为数组当中没有放入空格,所以要在上述循环结束后自己放入
start++;//并++一次,以便下次存放单词
}
}
//将第一个单词也放到新数组当中
for (i = 0; arr[i] != ' '; i++)
{
ch[start] = arr[i];
start++;
}
printf("%s\n", ch);
return 0;
}
第四种方法
第四种方法更为精简,不过也有一点点的瑕疵
采用递归的方式,这个方法大家注意看注释就行了
#include <stdio.h>
//递归倒序打印
void print()
{
char arr[101] = { 0 };
if (scanf("%s", arr) != EOF)//scanf在读取输入缓冲区的时候,遇到空格和文件结尾标志(windows的文件结尾标志是^z)就会停下来
{
print();
printf("%s ", arr);
}
}
int main()
{
print();
return 0;
}
为什么说这个方法有一点小的瑕疵呢,是因为他在最后无论怎样都会多打印一个空格,但是并不影响最终的输出结果
值得一提的是vs在输入文件结尾标志的^z时,需要输入三个才能让程序真正的停下来
第四种方法的运行结果:
卑微求赞老铁们