递归实现字符串逆序打印

01递归方式逆序打印

02递归和全局变量(把逆序的结果存入全局变量)

03递归和非全局变量(递归指针做函数参数)

#define _CRT_SECURE_NO_WARNINGS
#include"stdio.h"
#include"stdlib.h"
#include"string.h"

//01递归方式逆序打印
int reverse01(char *p)
{
	if (p == NULL)    //递归结束的异常条件
	{
		return -1;
	}
	if (*p == '\0')   //递归结束的条件
	{
		return 0;
	}
	reverse01(p+1);  //此时并不会接着执行打印,而是p的地址+1,不断入栈
	                 //开始递归调用,保护程序执行现场,以便程序返回
	                 //补充一个额外的知识点:p++相当于p=p+1,给p做了重新赋值。而p+1并不给p重新赋值

	printf("%c\n",*p);
}

//02递归和全局变量(把逆序的结果存入全局变量)
char g_buf[1000];//用全局变量把逆序的结果保存下来
int reverse02(char *p)
{
	if (p == NULL)     //递归结束的异常条件
	{
		return -1;
	}
	if (*p == '\0')    //递归结束的条件
	{
		return 0;
	}
	reverse02(p + 1);  

	//printf("%c\n", *p);
	//strncpy(g_buf, p, 1);    //每次拷的都是同一个位置,覆盖了
	strncat(g_buf, p, 1);      //不断向后连接,不会覆盖
}

//03递归和非全局变量(递归指针做函数参数)
int reverse03(char *p, char *bufResult)
{
	if (p == NULL)    //递归结束的异常条件
	{
		return -1;
	}
	if (*p == '\0')   //递归结束的条件
	{
		return 0;
	}
	reverse03(p + 1,bufResult);

	//printf("%c\n", *p);
	strncat(bufResult, p, 1);
}

void main()
{
	int ret = 0;
	char *p = "123456789";

	//ret = reverse01(p);

	/*memset(g_buf, 0, sizeof(g_buf));
	reverse02(p);
	printf("全局变量g_buf:%s\n", g_buf);*/

	char mybuf[1024] = { 0 };
	reverse03(p, mybuf);
	printf("局部变量mybuf:%s\n", mybuf);
}

关于reverse(p++)和reverse(p+1):
在递归函数中递归时,若使用reverse(p++),跟踪调试,发现每次递归传进去的p都是完整的“123456789”,并没有实现地址+1的操作。
下面是reverse(p++)调试截图:

reverse(p++)时反汇编:
递归实现字符串逆序打印_第1张图片

下面是reverse(p+1)的调试截图:


reverse(p+1)时反汇编:
递归实现字符串逆序打印_第2张图片

分析:

       从上面的调试可以看出:p++时执行死循环,没有ECX寄存器控制(ECX 是计数器(counter), 是重复(REP)前缀指令和LOOP指令的内定计数器)。而p+1时,则lea  ecx,[esi+1],最后对esi进行逐个pop。 

       突然觉得这个话题好低能,看上面的递归,这里用p++和p+1时,对于传入的参数值不同,前者就是p,而后者是p+1。虽然p++会对后续使用p带来影响,但此处的递归函数reverse01需要的是p所指向的下一个地址,可写成p+1或者++p。但是++p改变了p值,反而后续输出则变得不正常。
通过反汇编,也可以看到reverse(p++)成了一个死循环,因为每次reverse(p++)传入的参数都是p,虽然p发生了变化,但是用不上!

       p++相当于p=p+1,给p做了重新赋值,p发生了更新。而p+1并不给p重新赋值,p不会发生更新。

void main()
{
	char *p = "123456";
	for (; *p != '\0' ; p+1)     //死循环不断输出"1"
	{
		printf("%c", *p);
	}
}
所以什么时候用p++什么时候用p+1,一定要明白这两个的不同之处。

你可能感兴趣的:(递归,C语言,字符串逆序)