1、第7章函数及其应用第7章函数及其应用学习目标掌握函数的编写及调用方法,领会模块化程序设计方法。学习内容函数的定义、调用及声明,函数间参数的传递方法,模块化程序设计方法。下一页返回第7章函数及其应用7.1一个C程序实例7.2函数的定义和调用7.3变量的进一步讨论7.4函数应用实例7.5本章小结7.6实训上一页返回7.1一个C程序实例【例7-1】用调用函数的方式计算整数的阶乘。【程序代码】#includestdio.hlongfac(intn)/*fac()是自定义函数,用于计算n的阶乘*/inti;longf=1;for(i=1;iy?x:y;returnz;voidmain()inta,b,c
2、,max;printf(entera,b,c:);上一页下一页返回7.2函数的定义和调用scanf(%d,%d,%d,&a,&b,&c);max=mymax(mymax(a,b),c);/*函数嵌套调用*/printf(max=%dnn,max);程序输出结果为:程序中函数mymax()的功能是从两个数中返回较大数。为了使用函数mymax()找出3个数中的最大数,程序采用了2次调用,即先调用函数mymax()找出2个数中的大数,然后再用这个大数和第3个数作实数,调用函数mymax()找出最大数。上一页下一页返回7.2函数的定义和调用7.2.3函数的声明函数的使用原则是先定义后使用,也就是说,函
3、数的定义位置原则上应出现在函数调用位置之前,例7-1和例7-2遵循的就是这个原则。但是,如果在调用函数前对被调函数进行声明,那么调用函数和被调函数的位置就可以随意安排。函数声明方法:函数值类型函数名(形参列表);例7-2中函数位置按以下形式安排,程序也能正常执行。#includestdio.h#includemath.hfloatarea(floata,floatb,floatc);/*函数声明*/main()上一页下一页返回7.2函数的定义和调用floatx,y,z,sf;printf(请输入三边:);scanf(%f,%f,%f,&x,&y,&z);sf=area(x,y,z);/*调用函
4、数*/printf(三边为%5.2f,%5.2f,%5.2f的三角形面积等于%5.2fn,x,y,z,sf);floatarea(floata,floatb,floatc)/*定义函数*/floath,s;h=0.5*(a+b+c);s=(sqrt(h*(h-a)*(h-b)*(h-c);return(s);上一页下一页返回7.2函数的定义和调用提示:(1)函数声明与函数定义的区别在于,函数声明是通过语句来完成,没有函数体,作用类似于变量说明。(2)当函数值类型是默认类型(int型)时,不论被调函数与调用函数位置如何安排,函数声明都可以忽略。但是能够坚持函数声明是一个好的编程习惯。上一页下一页
5、返回7.2函数的定义和调用7.2.4函数间的数据传递函数是用来实现具体功能的模块,所以它必然要和程序中的其他模块交换数据。一个函数可以从函数之外获得数据,并可以向其调用者返回数据,这些数据主要是通过函数的参数和函数返回值来传递的。C语言中,常见的参数传递方式有2种:值传递和地址传递。本节介绍值传递方式,地址传递将在第九章介绍。值传递的特点是函数调用时实参仅仅将其值赋给形参。当实参为变量时,实参变量和形参变量在存储空间上是分开的,因此函数中对形参变量值的任何修改都不会影响到相应的实参变量,前面介绍的实例中均采用这种方式进行参数传递。上一页下一页返回7.2函数的定义和调用【例7-5】交换两个变量的
6、值。【程序代码】#includestdio.hvoidswap(intx,inty);voidmain()/*函数声明*/inta=10,b=20;printf(a=%d,b=%dn,a,b);swap(a,b);printf(a=%d,b=%dnn,a,b);voidswap(intx,inty)/*交换两个参数变量的值*/上一页下一页返回7.2函数的定义和调用intz;z=x;x=y;y=z;printf(x=%d,y=%dn,x,y);程序输出结果为:小测验从程序输出结果来看,函数swap()并没有完成交换两个变量值的任务,为什么呢?提示:值传递方式的好处是减少了调用函数和被调函数之间的
7、数据依赖,增强了函数自身的独立性。上一页返回7.3变量的进一步讨论一个变量在程序中的哪个函数中都能使用吗?答案是否定的。根据变量在程序中的使用范围,可以将变量分为局部变量和全局变量。局部变量又称为内部变量,是指在函数内部定义的变量,其有效范围仅限于本函数内部。全局变量又称为外部变量,是指在函数外部定义的变量。其有效范围从定义变量的位置开始直到程序结束。【例7-6】局部变量和全局变量的使用。#includestdio.hintx;/*定义x为全局变量*/intfun1(intx)/*形参x为局部变量*/下一页返回7.3变量的进一步讨论intfun2(inty)x=y+5;returnx*x;in
8、tx;/*函数内部定义x为局部变量*/returnx*x;main()x=0;/*给全局变量x赋值*/printf(Theresultinfun1:%dn,fun1(5);printf(Theresultinfun2:%dn,fun2(5);printf(x=%dn,x);/*输出全局变量x*/上一页下一页返回7.3变量的进一步讨论程序输出结果为:程序说明:本例中有3个变量x:一个是全局变量x,一个是函数fun1()的形参x,第3个是在函数fun2()中定义的局部变量x,它们3个虽然同名却是不同的对象。虽然全局变量的有效范围是整个程序,但是在局部变量的作用范围内,同名全局变量暂时不起作用。提示
9、:为了使程序清晰易读,程序中不同用途的变量最好不要使用相同的变量名,以免造成混乱。上一页下一页返回7.3变量的进一步讨论程序中不论是形参x还是局部变量x,都是在函数执行时为其分配存储单元,一旦函数执行结束,所占内存空间即刻释放,也就是说它们的生存期仅限于函数执行期间,这种变量属于动态存储变量。【例7-7】下面程序希望输出1n之间各数的阶乘。#includestdio.hlongfun(inti)longf=1;/*定义f为局部变量并赋初值1*/f=f*i;returnf;上一页下一页返回7.3变量的进一步讨论main()intn,m;printf(pleaseentern:);scanf(%d
10、,&n);for(m=1;m0;i-)a+=sub2(i);/*函数调用*/return(a);intsub2(intn)/*函数定义*/return(n+1);程序分析:程序中有3个函数:1个main()函数和2个自定义函数。程序执行时,主函数调用sub1()函数,sub1()函数又调用sub2()函数,sub2()函数执行完后会返回sub1()函数,sub1()函数会返回主函数。这种多层调用的关系称为函数的嵌套调用。图7-1是函数嵌套调用示意图。小测验写出例7-8的输出结果。上一页下一页返回7.4函数应用实例【例7-9】函数的递归调用。#includestdio.hintage(intn)
11、inta;if(n=1)a=10;elsea=age(n-1)+2;/*递归调用*/return(a);main()printf(age=%dn,age(5);上一页下一页返回7.4函数应用实例程序分析:程序中主函数main()调用了函数age(),而函数age()在变量n不等于1时,又调用了age()函数自己,这种调用的关系就叫函数的递归调用。图7-2给出了age()函数的递归过程。【例7-10】算术练习程序。让计算机给小学生出10道简单的算术题(两位整数范围内,由随机函数rand()产生),学生输入答案后,计算机会自动判定是否正确,最后输出学生的得分(每道题10分)。算术题有加、减、乘、除
12、4种。【编程思路】本题采用模块化程序设计方法,4种运算在4个子模块(函数)中完成,main()函数为主控程序,根据用户的选择,调用相应的子模块,其模块结构如图7-3所示。上一页下一页返回7.4函数应用实例【程序代码】#includestdio.h#includetime.h#includestdlib.hvoidfun1();/*函数声明*/voidfun2();/*函数声明*/voidfun3();/*函数声明*/voidfun4();/*函数声明*/main()/*主控函数,显示菜单*/intn;while(1)上一页下一页返回7.4函数应用实例printf(n=算术练习程序=n);pri
13、ntf(n1.加法printf(n2.减法printf(n3.乘法printf(n4.除法printf(n0.退出printf(n=n);n);n);n);n);n);上一页下一页返回7.4函数应用实例printf(请选择(0-4):);scanf(%d,&n);switch(n)/*根据选择调用相应的函数*/case1:fun1();break;case2:fun2();break;case3:fun3();break;case4:fun4();break;case0:exit(0);/*函数exit(0)用于正常退出程序*/voidfun1()/*加法函数*/上一页下一页返回7.4函数应用
14、实例inti,a,b,m,k=0;for(i=0;i10;i+)a=10+rand()%90;b=10+rand()%90;printf(%d+%d=,a,b);scanf(%d,&m);if(m=(a+b)k+=10;printf(你的得分是:%dn,k);voidfun2()/*减法函数*/上一页下一页返回7.4函数应用实例inti,a,b,m,k=0;for(i=0;i10;i+)a=10+rand()%90;b=10+rand()%90;printf(%d-%d=,a,b);scanf(%d,&m);if(m=(a-b)k+=10;printf(你的得分是:%dn,k);上一页下一页返
15、回7.4函数应用实例voidfun3()/*乘法函数*/inti,a,b,m,k=0;for(i=0;i10;i+)a=10+rand()%90;b=10+rand()%90;printf(%d*%d=,a,b);scanf(%d,&m);if(m=(a*b)k+=10;printf(你的得分是:%dn,k);上一页下一页返回7.4函数应用实例voidfun4()/*除法函数*/inti,a,b,m,k=0;for(i=0;i10;i+)a=10+rand()%90;b=10+rand()%90;printf(%d/%d=,a,b);scanf(%d,&m);if(m=(a/b)k+=10;p
16、rintf(你的得分是:%dn,k);上一页下一页返回7.4函数应用实例程序执行后的主界面为:选择1,做加法练习时,执行过程为:选择3,做乘法练习时,执行过程为:上一页返回7.5本章小结1.编程时使用函数的好处有以下几个方面:(1)程序结构清晰,可读性好。(2)减少重复编码的工作量。(3)可多人共同编制一个大程序,缩短程序设计周期,提高程序设计和调试的效率。可以说掌握好函数是学好C语言的关键之一。2.函数的使用原则是先定义后使用。3.函数定义。根据实际问题确定函数首部,编写函数体。对初学者来说,定义函数时,如何设置形参是一个难点。可以这样考虑:形参是虚拟变量,它要从调用函数中得值,那么该函数是
17、否需要从调用函数中接受数据,需要接受几个什么类型的数据,以此来确定有没有必要设置形参,设置几个形参。例如,有函数首部为:floatdis(floatm1,floatm2,floatd)表示将从调用函数中接受3个float类型的数据。下一页返回7.5本章小结4.函数调用时,实参与形参的个数应相同,类型应一致。实参与形参按顺序对应,一一传递数据。5.函数间数据传递方法有两种:值传递和地址传递。当实参为常量、变量或表达式时均采用单向值传递,形参仅从实参得到值,形参值的变化对实参没有影响。6.函数声明。原则上以下两种情况可以不进行函数声明:(1)函数定义在前,调用函数在后。(2)函数定义在后,但函数的
18、类型是int型。当调用在前,被调函数定义在后,且被调函数的类型不是int型时,必须对被调函数进行声明。7.函数可以嵌套调用和递归调用。8.变量。按照变量的作用范围,变量分局部变量和全局变量;按照变量的生存期,变量分静态存储变量和动态存储变量。上一页返回7.6实训实训1【实训内容】函数的定义和调用【实训目的】掌握函数的定义和调用方法【实训题目】(1)下面程序希望计算两个数的平均值,写出程序的预期结果,并上机验证。#includestdio.hdoubleaverage(int,int);/*函数声明*/main()inta,b;doublev;a=10;b=11;下一页返回7.6实训v=aver
19、age(a,b);/*函数调用*/printf(%lfn,v);doubleaverage(intx,inty)/*函数定义*/doublez;z=(x+y)/2;return(z);(2)下面程序的功能是计算两个圆的周长之差,请把程序补充完整,并上机验证。#includestdio.h;上一页下一页返回7.6实训main()doubler1,r2,len;r1=3.3;r2=5.5;len=printf(len=%lfn,len);doublemylen(doubler)doublelength;length=2*3.14159*r;上一页下一页返回7.6实训实训2【实训内容】函数间数据的传
20、递【实训目的】掌握单向值传递方法【实训题目】分析下面程序的输出结果,并上机验证。#includestdio.hintf(intx,inty,intcp,intdp)cp=x*x+y*y;dp=x+x-y*y;return(cp);return(dp);上一页下一页返回7.6实训main()inta=4,b=3,c=5,d=6;f(a,b,c,d);printf(%d%dn,c,d);上一页下一页返回7.6实训实训3【实训内容】函数的编写【实训目的】掌握函数的编写方法【实训题目】函数prime()是一个判断整数是否为素数的函数,调用该函数输出1000以内的素数,要求输出每行10个数。主函数已经给
21、出,请编写函数prime()。intprime(intn)/*判断参数n是否为素数*/voidmain()/*主函数*/上一页下一页返回7.6实训intn;intc=0;/*统计素数个数,用以控制输出格式*/printf(1000之间的素数如下:n);for(n=2;n=1000;n+)if(prime(n)=1)/*函数调用*/printf(%6d,n);c+;if(c%10=0)printf(n);/*每行输出10个素数*/上一页下一页返回7.6实训实训4【实训内容】变量。【实训目的】掌握局部变量和静态变量的特性。【实训题目】分析下面程序的输出结果,然后上机验证。程序一#includest
22、dio.h#includemath.hvoidfun1();voidfun2();voidmain()intx=1;上一页下一页返回7.6实训fun1();printf(%dn,x);voidfun1()intx=2;fun2();printf(%dn,x);voidfun2()intx=3;printf(%dn,x);上一页下一页返回7.6实训程序二#includestdio.h#includemath.hvoidfun();voidmain()fun();fun();fun();voidfun()intx=0;x=x+1;printf(%dn,x);上一页下一页返回7.6实训程序三#includestdio.h#includemath.hvoidfun();voidmain()voidfun()staticintx=0;x=x+1;printf(%dn,x);fun();fun();fun();上一页返回图7-1函数的嵌套调用返回图7-2age()函数的递归过程返回图7-3模块化结构示意返回
©2010-2024 宁波自信网络信息技术有限公司 版权所有
客服电话:4008-655-100 投诉/维权电话:4009-655-100