在调用一个函数的过程中又出现直接或间接地调用该函数本身,称为函数的递归调用

递归函数

在调用一个函数的过程中又出现直接或间接地调用该函数本身,称为函数的递归调用

在调用一个函数的过程中又出现直接间接地调用该函数本身,称为函数的递归调用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语句,行末不需加分号。