一道交换字符串的题目

目录

一、题目描述

二、分析思路

三、Strlen()函数的实现

 四、循环实现reverse_string

五、递归实现reverse_string 

六、代码展示


一、题目描述

编写一个函数reverse_string(char *string)(递归实现)

 实现:将参数字符串中的字符反向排列,不是逆序打印。

要求:不能使用C函数库中的字符串操作函数。

比如:char arr[] = "abcdef";

主要目的就是考虑如何使用递归实现字符串中的字符反向排列;使对递归函数有一个更深层次的理解。

大体的思路可以用下面的代码展示;问题的关键就是如何写出reverse_string()函数。

#include<stdio.h>
int main()
{
	char arr[] = "abcdef";
	reverse_string(arr);
	printf("%s", arr);
	return 0;
}

二、分析思路

把步骤分为两步走;第一步先先考虑使用循环来实现;第二步考虑怎么转化为递归;归结起来就是在使用了循环实现之后,转换为递归实现。在实先过程中会用到Strlen()函数,总结如下:

三、Strlen()函数的实现

其实Strlen()函数的实现有很多方式,既可以考虑使用循环实现,也可以考虑使用递归来实现;

先给出Strlen()函数的实现过程;方便后面使用:

用循环实现Strlen()函数:

int Strlen(char* arr)
{
	int count = 0;
	while (*(arr) != '/0')
	{
		count++;
		arr++;
	}
	return count;
}

 *arr找到arr数组对应的元素,然后判断是否为\0,不是就把地址+1;继续判断;在此过程需要一个变量count记录每往后一次判断的次数。

用递归实现Strlen()函数

int Strlen(char *arr)
{
	if (*(arr) != '\0')
	{
		return 1 + Strlen(1 + arr);
	}
	else
	{
		return 0;
	}
}

 四、循环实现reverse_string

要实现交换很简单,只需要实现a与f交换,b与e交换,c与d交换就可以;假设a的下标为left;f的下标为right; 通过下标实现将a与f交换,然后left++;right--实现单次交换;然后停下来的条件是下标left 大于等于right; 等于情况时,只有一个元素,交不交换都可以;在这里知道right下标需要知道arr数组长度,用自己写的Srlen()函数实现;因为题目说了不能使用c语言中的库函数。

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--;
	}
}

其实while循环里面有另外一种写法和上述写法等价;如下:

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--;
	}
}

 两种方法说明:*(arr+left)等价于arr[left];

在这里说一下reverse_string的形参部分;实参用数组名作为参数,数组名是数组首元素的地址,在这里形式参数用指针接收地址,完全符合逻辑,没有任何问题的

另外一个角度来说;要对arr这个数组进行修改之后在打印,采用传址调用;也是没有问题的
但是这里本质上还是指针

这里可以写为char arr[]:因为实参是数组,传给形参时候,形参用数组接收实参传来的数组,是可行的;代码就如下面所示了:

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--;
	}
}

此处不可以换成sizeof()来计算arr;因为sizeof(arr)表示计算arr这个指针变量的大小(32位平台指针大小为4个字节;64位平台为8个字节);right值就为3了。

  这里注意点是形式参数里面的arr与main函数里面的arr不是同一个,因为形参变量可以与实参变量相同,建议为避免混淆,尽量不同为妙;

五、递归实现reverse_string 

在使用递归来实现字符串中字符交换时;其他部分大体相同,不同之处就在于reverse_string()函数的实现;针对本题 递(传递)归(回归)思想:
    要实现字符串a b c d e f \0的逆序步骤;
    1、交换a与f,再使用reverse_string()函数逆序bcde 
    2、bcde可以再次分为交换b和e,然后使用reverse_string()函数逆序cd
    3、cd可以再次分为交换c和d,然后使用reverse_string()函数逆序空字符串(什么都没有了)
    但是这样是有错误的,先实现大体框架,后面再修改吧(先把框架搭起来,然后再此基础上面慢慢修改)

void reverse_string(char* arr)
{
	int length = Strlen(arr);
	char tmp = *(arr);	
	*(arr) = *(arr + length - 1);
	*(arr + length - 1) = tmp;
	reverse_string(arr + 1);	
}

但是这里这样写是有问题的,因为如果逆序完a与f之后,字符串变为fbcdea \0

再进行逆序,程序就以为你要逆序bcdea; 所以在执行*(arr)=*(arr+length-1)之后,应该暂时给

*(arr+length-1)='\0';    然后执行下一次逆序reverse_string(arr + 1);最后把执行

*(arr+length-1)=tmp  也就是应该这样来写:

char tmp = *arr;
	int length = Strlen(arr);
	*arr=*(arr+length-1);
	*(arr+length-1)='\0';
	reverse_string(arr + 1);
	*(arr+length-1)=tmp;

但是还是有个问题:reverse_string()里面又套了一个reverse_string();递归没有限制条件,会一直死循环递归下去; 所以第二个reverse_string()处应该加上条件(中间递归的字符串个数要大于2);所以要在reverse_string()前面加上if(Strlen(arr+1));结果如下:

char tmp = *arr;
	int length = Strlen(arr);
	*arr=*(arr+length-1);
	*(arr+length-1)='\0';
	if(Strlen(arr+1) >= 2)
		{
            reverse_string(arr + 1);
        }
	*(arr+length-1)=tmp;

这样就使用递归解决了字符串中字符的交换。    

六、代码展示

下面给出递归实现的整个演示过程:

循环实现的总过程:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int Strlen(char* arr)
{
	if (*(arr) != '\0')
	{
		return 1 + Strlen(1 + arr);
	}
	else
	{
		return 0;
	}
}

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[] = "abcdef";
	reverse_string(arr);
	printf("%s", arr);
	return 0;
}

递归实现的总过程: 

#include<stdio.h>
int Strlen(char* str)
{
	int count = 0;
	while (*str != '\0')
	{
		count++;
		str++;
	}
	return count;
}
void reverse_string(char* str)
{
	int left = 0;
	int right = Strlen(str) - 1;
	char tmp = *(str+left);
	*(str + left) = *(str + right);
	*(str + right) = '\0';
	if(Strlen(str)>=2)
	{
		reverse_string(str + 1);
	}	
	*(str + right) = tmp;
}
int main()
{
	char arr[] = "abcdef";
	reverse_string(arr);
	printf("%s", arr);
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值