【C语言】-字符串逆序

题目:编写一个函数 reverse_string(char * string)(递归实现)实现:将参数字符串中的字符反向排列。要求:不能使用C函数库中的字符串操作函数。

这里先提一点,很多人拿到这道题的时候就把题意理解错了,题目的要求是将字符串的字符反向排列,而不是把字符串的字符反向打印到屏幕上。假使我们使用数组存放的这组字符串,那么函数的功能应该就是是数组中的字符串按逆序排列。

先来看递归写法:

算法思想:
先举一个简单的例子,我们要将ABCDE五个字符逆序,那么我们是不是应该让A和E交换,B和D交换,E的位置不变。
理解好这个简单的逻辑之后,我们把这五个字符放到数组arr中,那么是不是就是交换arr[0]和arr[4],arr[1]和arr[3],arr[2]的位置不变。
而根据前面我们所学的知识,交换两个变量的值,是不是要定义一个中间变量来做媒介。
用递归的方法我们应该怎么做呢?
我们可以按逻辑顺序捋一下这个问题,假使我们这里定义了一个中间变量tmp.
这个数组arr[]=“ABCDE”,传进来之后,由于数组是随机的,所以数组最右边元素的下边我们不知道,而根据我们前面的知识,我们知道解决这个问题可以用strlen函数来求出字符串的长度,再减一就是数组最右边元素的下标。由于题目要求我们不允许调用任何库函数,那么我们就自己写一个my_strlen函数,来实现strlen函数的功能就可以了。
接下来我们借用中间变量交换arr[left]和arr[right]的值,也就是A和E
那么接下来我们是不是应该让BCD进入到下一个函数中来交换B和D值呢。
我们知道,只要我们给数组的地址加一,数组就会从第二个元素开始,所以我们可以和简单的让数组从B开始,那么我们应该怎样让它从D结束,换个说法就是我们要怎样把这个E给去掉,这是很多人在写这个递归的时候面临的最大的问题
接下来介绍大家一种做法。
我们在交换A和E的时候,我们可以先把A放到tmp中,然后把E的值放到A中去,而注意,这个时候我们先不要把tmp里A的值放到E中,而是给E中放一个’\0’,我们都知道字符串是以\0结尾的,然后我们进入到下一个函数,这样进入到下一个函数的元素就是BCD了。
而等到函数结束后,我们再把tmp里的内容放到最后一位的位置中去,这样巧妙地改变一下交换的顺序,我们就可以完成这次递归操作了。
当然这里我们还需要找出这个递归的限制条件,如果这个递归没有限制条件一直递归下去那么就会造成栈溢出现象了。
什么时候我们就可以结束这次递归了呢。我们发现ABCDE等到进入递归函数时的元素只剩下C的时候我们就没必要再递归了。所以限制条件是判断是判断字符串的个数是不是大于1,如果比1大,那就继续递归操作交换左右两边元素的值,如果比1小,那就没必要再进行递归操作,直接结束函数即可

代码如下:

#include<stdio.h>
int my_strlen(char* str)

{
	int count = 0;
	while (*str)
	{
		count++;
		str++;
	}
	return count;
}

void reverse_string(char arr[])
{
	char tmp = arr[0];
	int len = my_strlen(arr);
	arr[0] = arr[len - 1];
	arr[len - 1] = '\0';
	//中间字符串的逆序
	if (strlen(arr+1)>1)
		reverse_string(arr+1);
	arr[len - 1] = tmp;
}
int main()
{
	char arr[] = "abcdefg";
	//逆序-逆置-arr
	//fedcba
	reverse_string(arr);
	printf("%s\n", arr);
	return 0;
}

这里对my_strlen函数里的内容补充一点,我们看完都知道那里的条件是判断进来的元素是不是不等于’\0’
而我们只在判断框里写了*str。
其实他的实质也是断进来的元素是不是不等于’\0’,只不过简化了一下。那是因为**’\0’的ASCII码值为0**,所以当’\0’进来之后,判断条件为0,就会结束循环。

我们再来介绍一种非递归的写法。

非递归写法相较于上面的递归写法可能会简单一些。
其实质还是元素互换,只不过我们不需要再逐渐减少元素的值了,这里我们采用简单的一个循环就可以解决了。
我们用left和right代替左右两边元素的下标,交换完之后,给左下标加1,右下标减1,知道左下标比右下标大的时候我们就可以结束循环了

代码如下:

#include<stdio.h>
int my_strlen(char* str)

{
	int count = 0;
	while (*str)
	{
		count++;
		str++;
	}
	return count;
}

void reverse_string(char arr[])
{
	int left = 0;
	int right = strlen(arr)-1;
	while (left<right)
	{
		char tmp = arr[left];
		arr[left] = arr[right];
		arr[right] = tmp;
		left++;
		right--;
	}
}
int main()
{
	char arr[] = "abcdefg";
	//逆序-逆置-arr
	//fedcba
	reverse_string(arr);
	printf("%s\n", arr);
	return 0;
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值