目录
13.1 函数的嵌套调用
13.1.1 函数嵌套的概念
函数嵌套是指在一个自定义函数的函数体中,又出现了另外自定义函数的调用。如函数a调用函数b,函数b又调用函数c等。
13.1.2 程序实例
已知组合数,求对于任意m、n时的值。程序如下:
float fac(int k) /* 定义求k!的函数 */
{
int i;
float f;
for(i=1,f=1;i<=k;i++)
f*=i;
return(f);
}
float cmn(int m,int n) /* 定义函数 */
{
float res;
res=fac(m)/(fac(n)*fac(m-n)); /* 调用函数fac() */
return(res);
}
void main()
{
int m,n;
float t;
printf("m,n=");
scanf("%d,%d",&m,&n);
t=cmn(m,n); /* 调用函数cmn() */
printf("C(%d,%d)=%f\n",m,n,t);
}
13.2 函数的递归调用
递归函数是由递归定义产生的,若在定义一个函数的过程中直接或间接地调用了被定义的函数本身,那么这种定义就是递归定义,所定义的函数称为递归函数。递归函数可以使程序简洁、代码紧凑,但只有能使用递归方法描述的问题,才能使用递归函数实现。下面分两种情况对递归函数进行讨论。
13.2.1 公式递归问题
- 概念
能够使用一个递归公式描述的问题归类为公式递归问题。 公式递归基本过程分两步:①用递归公式描述问题;② 将递归公式函数化。
- 实例
用递归方法求。
①用递归公式描述问题:
若使用函数sum(n)表示累加和,则:
②将递归公式函数化:
//递归函数
int sum(int n)
{
if(n==1)
return(1);
else
return(sum(n-1)+n);
}
//主函数
main()
{
int n;
scanf("%d",&n);
printf("%d\n",sum(n));
}
- 注意
递归处理是由计算机自动完成的,包括两个过程:
①由高到低的递推处理,将问题规模逐步缩小,直至运算规模不能分解时为止,此时必然有一个最小规模值(n=1的情况);
②由低到高逐级回溯,从最小规模值开始,逐级求得上层数据,直到解决问题为止。
13.2.2 非公式递归问题
- 概念
有的问题不能直接用一个递归公式进行描述,但处理过程包含了递归的思路,这一类问题称为非公式递归问题(又称过程递归)。
- 实例
最典型的过程递归问题——汉诺塔问题!
题目介绍:有三个柱和n个大小各不相同的盘子,开始时, 所有盘子以塔状叠放在柱A上,要求按一定规则,将柱A上的所有盘子借助于柱C移动到柱B上。移动规则为:⑴ 一次只能移动一个盘子。⑵ 任何时候不能把盘子放在比它小的盘子的上面。
实现程序如下:
#include <stdio.h>
long i=0;
void main()
{
int disks;
void hanoi(int,char,char,char);
printf("Number of disks: ");
scanf("%d",&disks);
printf("\n");
hanoi(disks,'A','C','B');
}
void move_disk(char src, char dst)
{
if(i==5)
{
printf("\n");
i=0;
}
i++;
printf("%c --> %c ",src,dst);
}
void hanoi(int n, char src, char mid, char dst)
{
void move_disk(char,char);
if (n==1)
{
move_disk(src,dst);
return;
}
hanoi(n-1,src,dst,mid);
move_disk(src,dst);
hanoi(n-1,mid,src,dst);
}
13.3 数组与函数
13.3.1 数组元素作函数参数
- 概念
数组元素作为函数的参数时,只传送作为实参的数组元素,此时按使用其他简单变量的方法使用数组元素(值传递)。
数组元素作函数实参调用函数时,传给形参的值是数组元素的值,函数执行时开辟独立的内存空间,与源数组的内存空间不发生关系,函数执行结果对源数组数据没有任何影响。
- 实例
把一个整型数组的所有素数找出来。实现程序如下:
#include "math.h"
//判断素数的函数prime()
int prime(int k)
{
int sk,i;
int flag=1;/* 设置素数标志 */
sk=sqrt(k);
for(i=2;i<=sk;i++)
if(k%i==0)
{
flag=0; /* k不是素数 */
break;
}
return(flag);
}
void main()
{
int prime(int);
int i,natural[10];
for(i=0;i<10;i++)
scanf("%d",&natural[i]);
for(i=0;i<10;i++)
{
if(prime(natural[i]))
printf("%d ",natural[i]);
printf("\n");
}
}
13.3.2 一维数组名作为函数参数
- 概念
C语言中的数组名有两种含义,一是标识数组,二是代表数组的首地址,数组名的实质就是数组的首地址。因此,数组名作为函数参数与数组元素作为函数的参数有本质的区别。数组名作为函数参数时传送的是数组的开始地址,是一种传址调用。形参数组和实参数组要在各自的函数中进行等同的定义,函数调用执行时,形参数组映射到实参数组空间。
- 实例
设计一个对一维数组排序的sort()函数,并调用它实现数组排序。实现程序如下:
//排序函数sort()
void sort(int a[10])
{
int i,j,temp;
for(i=1;i<=9;i++)
{
for(j=0;j<=9-i;j++)
{
if(a[j]>a[j+1])
{
temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
}
}
}
}
void main()
{
void sort(int a[10]);
int i,data[10];
printf("data: ");
for(i=0;i<10;i++)
{
scanf("%d",&data[i]);
sort(data);
printf("rsult: ");
}
for(i=0;i<10;i++)
printf("%d ",data[i]);
}