递归函数
在调用一个函数的过程中又出现直接或间接地调用该函数本身,称为函数的递归调用。C语言允许函数的递归调用。例如:
int f(int x)
{
int y,z;
z=f(y); //在调用函数f的过程中,又要调用f函数
return (2*z);
}
以上是直接调用本函数,其调用过程如图6-3所示。
图6-3递归函数调用
图6-4表示的是函数间接调用本函数的过程。在调用f1函数过程中要调用f2函数,而在调用f2函数过程中又要调用f1函数。
图6-4函数间接调用本函数的过程
从图上可以看到,这两种递归调用都是无终止的自身调用。显然,程序中不应出现这种无终止的递归调用,而只应出现有限次数的、有终止的递归调用,这可以用if语句来控制,只有在某一条件成立时才继续执行递归调用,否则就不再继续。
在C语言中,为了防止陷入无限递归调用的状态,避免一些严重错误的发生,对于递归函数的设计,是有严格的数学模型的,并不是所有的问题都可以设计成递归函数。
一个函数能设计成为递归函数,在数学上必须具备以下2个条件。
(1)问题的后一部分与原始问题类似。
(2)问题的后一部分是原始问题的简化。
设计递归函数的重点是建立问题的数学模型,一旦建立了正确的递归数学模型,就可以很容易地编写出递归函数。
【例6-11】编写程序,要求从键盘输入一个正整数n,计算n!。
分析:n!的数学表达式为:
从n!的数学模型,不难看出,它满足数学上对递归函数的两个条件:
(1)(n-1)!与n!是类比的;
(2)(n-1)!是n!计算的简化。
设计递归函数long fac(int n)用于求n!,算法流程如图6-5所示。
程序代码如下:
#include <stdio.h>
long fac(int); //函数声明
int main()
{
int n; //n为需要求阶乘的整数
long y; //y为存放n!的变量
printf(″please input an integer :″); //输入的提示
scanf(“%d”,&n); //输入n
y=fac(n); //调用fac函数以求n!
printf(“%d!=%d”,n,y); //输出n!的值
return 0;
}
long fac(int n) //递归函数
{
long f;
if (n==0||n==1)
f=1; //0!和1!的值为1
else
f=fac(n-1)*n; //n>1时,进行递归调用
return f; //将f的值作为函数值返回
}
程序运行结果:
please input an integer:10↙
10!=3628800
图6-5 函数间接调用本函数的过程
许多问题既可以用递归方法来处理,也可以用非递归方法来处理。在实现递归时,在时间和空间上的开销比较大,但符合人们的思路,程序容易理解。
6.2.3预处理
C语言中,除了用来完成程序功能的说明语句和可执行语句之外,还有一些编译预处理,用来向编译系统发布信息或命令,告诉编译系统在对源程序进行编译之前应做些什么事。
所有编译预处理都是以“#”开头,单占源程序中的一行,一般是放在源程序的首部。需要注意的是:编译预处理不是C语句,行末不需加分号。