函数实现之前 先看一个例子
void fun(int i)
{
if (i > 0)
fun(i / 2);
printf("%d ",i);
}
int main(void)
{
fun(10);
return 0;
}
输出结果是什么?
这是《c语言深度剖析》中的一个例子 在这个例子中 printf(“%d ”,i);语句是fun函数的一部分 必定执行一次fun函数,就要打印一次。函数展开过程如下:
void fun(int i)
{
//fun(i/2);
if (i > 0)
{
if (i / 2 > 0)
{
if (i / 4 > 0)
{
....
}
printf("%d ",i/4);
}
printf("%d ", i / 2);
}
printf("%d ", i );
}
是不是清晰很多?
同样的思路 来完成reverse_string(char *string)函数 代码如下:
/*编写一个函数reverse_string(char * string)(递归实现)*/
#include<stdio.h>
#include<math.h>
void reverse_string(char *string)
{
if (*(++string) != '\0')
reverse_string(string);
printf("%c",*(string-1));
}
int main()
{
char *a = "abcde";
reverse_string(a);
printf("\n");
return 0;
}
在这个程序的编写中 出现了很多意想不到的问题 看看下面的写法
void reverse_string(char *string)
{
if (*string != '\0')
reverse_string(string++);
if (*string != '\0')
printf("%c", *string);
}
int main()
{
char *a = "abcde";
reverse_string(a);
printf("\n");
return 0;
}
输出结果是什么?
来分析一下:在实现递归的过程中 我们使用了这样一句代码:
reverse_string(string++);
后置++ 的操作方式 是首先将值进行相应的操作 然后进行自加
string一开始指向的是字符串的首地址处 可以狭义的理解为&a的地方 然后reverse_string(string);string++;++操作后string此时指向的狭义的理解为&b的地方(狭义的理解),但是函数的调用reverse_string(string)还是操作&a的地址 相当于死循环 程序不断地压栈 导致栈溢出 。
将程序改成前置++ 结果又会怎么样:
#include<stdio.h>
#include<math.h>
void reverse_string(char *string)
{
if (*string != '\0')
reverse_string(++string);
if (*string != '\0')
printf("%c", *string);
}
int main()
{
char *a = "abcde";
reverse_string(a);
printf("\n");
return 0;
}
前置++ 首先进行的自加操作 另string指向字符串中&b的地方(狭义理解) 因此输出的结果中没有a
结束了吗?这个程序仅仅是将一个字符串常量进行翻转输出,在内存中字符串并没有改变
因此对程序进行如下修改:
#include <stdio.h>
void reverse_string(char * str)
{
int n = 0; //创建一个变量来记录字符串的长度
char *p = str; // str并不会发生改变
char tmp;
while (*p++ != '\0')
{
n++;
}
if (n > 1)
{
tmp = str[0];
str[0] = str[n - 1];
str[n - 1] = '\0';
reverse_string(str + 1);
str[n - 1] = tmp;
}
}
void main()
{
char string[] = "abcd";//char* a 为字符串常量 在静态区 具有只读属性 不可修改
reverse_string(string);
printf("%s\n", string);
}