c语言 函数.ppt
第12讲 函数(二)函数的嵌套调用函数的递归调用数组作为函数参数void printmessage(void);void printstar(void);main()printmessage();void printmessage(void)printstar();printf(“t*Welcome*n”);printstar();void printstar(void)printf(“t*n”);函数的嵌套调用 即在函数调用过程中又调用另一个函数可以多层嵌套调用mainmain函数函数a a函数函数b b函数函数调用调用a a函数函数调用调用b b函数函数结束结束结束结束结束结束调用流程弦截法如下:弦截法如下:(1)取两点)取两点x1x2,if(f(x1)和和f(x2)符号相反),符号相反),则则x0(x1,x2)。else则应改变则应改变x1,x2,直到直到f(x1),f(x2)异号为止。异号为止。注意:注意:x1,x2值不应差太大,以保证值不应差太大,以保证(x1,x2)区间内区间内只有一个根。只有一个根。(2)连接)连接f(x1)和和f(x2)两点,此线(即弦)交两点,此线(即弦)交x轴于轴于x。点点x坐标可用下式求出:坐标可用下式求出:再从再从x求出求出f(x)。)。(3)if(f(x)、f(x1)同符号),则同符号),则x0(x,x2),x1=x。else则则x2=x。(4)重复步骤()重复步骤(2)和()和(3),直到),直到|f(x)|为一个很小的数,例如为一个很小的数,例如10-6。此。此时认为时认为f(x)0。f(x2)x2x1xf(x1)f(x)用弦截法求 x3-5*x2+16*x-80=0 方程的根。嵌套调用示例 x1*f(x2)-x2*f(x1)x=f(x2)-f(x1)分别用几个函数来实现各部分功能:(1)用函数f(x)来求x的函数:x3-5*x216*x-80。(2)用函数xpoint(x1,x2)来求f(xl)和f(x2)的连线与x轴的交点x的坐标。(3)用函数root(x1,x2)来求(x1,x2)区间的那个实根。(4)在函数main()中对x1、x2取值。v显然,执行root函数过程中要用到函数xpoint,而执行xpoint函数过程中要用到f函数。函数设计include“math.h”float f(float x)/*定义定义f函数函数,以实现以实现f(x)*/float y;y=(x-5.0)*x+16.0)*x-80.0;return(y);float root(float x1,float x2)/*定义定义root函数,求近似根函数,求近似根*/float x,y,yl;y1f(x1);do x=xpoint(x1,x2);yf(x);if(y*yl0)/*f(x)与与f(x1)同同号号*/yl=y;x1=x;else x2=x;whi1e(fabs(y)=0.000001);return(x);main()/*主函数主函数*/float x1,x2,f1,f2,x;doprintf(input x1,x2:n”);scanf(%f,%f,&x1,&x2);fl=f(x1);f2=f(x2);while(fl*f2)=0);xroot(x1,x2);printf(A root of equation is 8.4f,x);float xpoint(float x1,float x2)/*定义定义xpoint函数,求出弦与函数,求出弦与x轴交点轴交点*/float y;y(xl*f(x2)-x2*f(x1)/(f(x2)f(xl);return(y);input x1input x1,x2x2:2 2,6 6A root of equation is A root of equation is 5.00005.0000函数的递归调用 在调用一个函数的过程中又出现直接或间接地调用该函数本身,称为函数的递归调用。例如:int f(int x)int y,z;z=f(y);return(2*z);在调用函数f的过程中,又要调用f函数,这是直接调用本函数,见下图:f函数函数 调用调用f函数函数下面是间接调用本函数:f1函数函数f2函数函数调用调用f2函数函数调用调用f1函数函数可以看到,这两种递归调用都是无终止的自身调用。显然,程序中不应出现这种无终止的递归调用,而只应出现有限次数的、有终止的递归调用,这可以用if语句来控制,只有在某一条件成立时才继续执行递归调用,否则就不再继续。有5个人坐在一起,问第5个人多少岁?他说比第4个人大2岁。问第4个人岁数,他说比第3个人大2岁,问第3个人,又说比第2个人大2岁。问第2个人,说比第1个人大2岁。最后问第1个人,他说是10岁。请问第5个人多大?分析:分析:递归调用示例-1age(5)=age(4)2 age(4)=age(3)2 age(3)=age(2)2 age(2)=age(1)2 age(1)=10可以用式子表述如下:10 (n=1)age(n)=age(n-1)+2 (n1)运算过程 age(5)age(5)=age(4)+2 =18 age(4)age(4)=age(3)+2 =16 age(3)age(3)=age(2)+2 =14 age(2)age(2)=age(1)+2 =12 age(1)=10第一阶段是第一阶段是“回推回推”,即将第,即将第n个个人的年龄表示为第(人的年龄表示为第(n-1)个人年龄个人年龄的函数,的函数,直到第直到第1个人的年龄。个人的年龄。第二阶段,采用第二阶段,采用递推递推方法,方法,从第从第1个人的已知年龄推算个人的已知年龄推算出第出第2个人的年龄(个人的年龄(12岁)岁)一直推算出第一直推算出第5个人的年个人的年龄(龄(18岁)为止。岁)为止。示例1程序清单一个递归的题可以分为“回推”和“递推”两个阶段。递归过程必须具有一个结束递归过程的条件。例如,age(1)10,是使递归结束的条件。可以用一个函数来描述上述递归过程:age(int n)/*求年龄的递归函数*/int c;/*c用作存放函数的返回值的变量*/if(n=1)c=10;else c=age(n-1)+2;return(c);main()printf(“%d”,age(5);运行结果如下:运行结果如下:1818递归调用示例-2用递归方法求n!分析:分析:求求n!可可以以用用递递推推方方法法,即即从从1开开始始,乘乘2,再再乘乘3,一直乘到,一直乘到n。递递推推法法的的特特点点是是从从一一个个已已知知的的事事实实出出发发,按按一一定定规规律律推推出出下下一一个个事事实实,再再从从这这个个新新的的已已知知的的事事实实出出发发,再再向向下下推推出出一一个个新新的的事事实实这这是是和和递递归不同的归不同的.求求 n!也也 可可 以以 用用 递递 归归 方方 法法,即即 5!=4!*5,而而4!=3!*4,1!=1。可用下面的递归公式表示:。可用下面的递归公式表示:1 (n=0,1)n!=(n-1)!*n (n1)示例2程序清单float fac (int n)float f;if(n0)printf(“nbi6次,biai3次,其中i每次为不同的值),则认为a数组大于b数组,并分别统计出两个数组相应元素大于、等于、小于的次数。main()int a10,b10,i,n=0,m=0,k=0;printf(enter array a:n);for(i0;jbi%d timesnai=bi%d timesnaiy)flag=1;else if(xy)flag-1;else flag0;return flag;数组名做函数参数数组名作函数参数,此时实参与形参都应用数组名(或用数组指针,见第9章。)例:有一个一维数组score,内放10个学生成绩,求平均成绩。程序如下:f1oat average(float array)int i;f1oat aver,sum=array0;for(i=1;j10;i+)sum=sum+array0;aver=sum/10;return(aver);main()f1oat score10,aver;int i;printf(input l0 scores:n”);for(i=0;i=10;i+)scanf(%f,&scorei);printf(n);aver=average(score);printf(“average score is%5.2f”,aver);用数组名作函数参数时,实参用数组名作函数参数时,实参数组数组与形参数组类与形参数组类型必须一致,但数组大小可以不一致,因为型必须一致,但数组大小可以不一致,因为C C编译编译对形参数组大小不做检查,只是对形参数组大小不做检查,只是将实参数组的首地将实参数组的首地址传递给形参数组址传递给形参数组,因此数组名作参数时,不是,因此数组名作参数时,不是“值传送值传送”,不是单向传递。上例中,不是单向传递。上例中scorenscoren和和arraynarrayn两个数组共占同一段内存两个数组共占同一段内存。形参数组也可以不指定大小,在定义数组时在数形参数组也可以不指定大小,在定义数组时在数组名后面跟一个空的方括弧,为了在被调用函数中组名后面跟一个空的方括弧,为了在被调用函数中处理数组元素,可以另设一个参数,传递数组元素处理数组元素,可以另设一个参数,传递数组元素的个数。的个数。在程序设计中可以有意识地利用这一特点改变实在程序设计中可以有意识地利用这一特点改变实参数组元素的值(如排序)。参数组元素的值(如排序)。说明用选择法对数组中10个整数按由小到大排序。void sort(int array,int n)int i,j,k,t;for(i0;i=n-1;i+)k=i;for(j=i+1;jmax)max=arrayij;return (max););main()()int a34=1,3,5,7,2,4,6,8,15,17,34,12;printf(”max value is dn”,max_value(a);运行结果如下:运行结果如下:max value is 34max value is 34