倒置字符串不改变单词顺序的四种方法

倒置字符串但不改变单词的顺序

前言:题目来自牛客网 倒置字符串
在这里插入图片描述

第一种方法

基本思路:
第一种方法就是先逆置整个字符串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时,需要输入三个才能让程序真正的停下来

第四种方法的运行结果:
在这里插入图片描述
卑微求赞老铁们

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

南山忆874

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值