(精品)C语言程序设计第12讲(函数)(2012级).ppt
2023/1/291 Program Design in C LanguagePage第十二讲第十二讲第七章第七章函数函数数组作为函数的参数数组作为函数的参数函数的嵌套调用函数的嵌套调用函数的递归调用函数的递归调用函数变量的作用域函数变量的作用域2023/1/292 Program Design in C LanguagePage数数组组元元素素做做函函数数实实参参,遵遵循循”值值传传送送”特特性性,此此时时形参为变量。形参为变量。数组名可做实参和形参,传送的是整个数组。数组名可做实参和形参,传送的是整个数组。在在用用数数组组名名做做函函数数参参数数时时,实实参参和和形形参参都都应应该该用用数数组(或指针变量)。组(或指针变量)。数组作为函数的参数数组作为函数的参数7.1.7 数组作为函数的参数 2023/1/293 Program Design in C LanguagePage数组元素作为函数参数举例数组元素作为函数参数举例:szdy1(intx,inty);szdy2(intx,inty);main()inta10,b45;szdy1(a7,b32);szdy2(b12,a4);szdy1(intx,inty)szdy2(intx,inty)(1)7.1.7 数组作为函数的参数 2023/1/294 Program Design in C LanguagePageszdy1(intx10);szdy2(intx45);main()inta10,b45;szdy1(a);szdy2(b);szdy1(intx10)szdy2(intx45)(2)7.1.7 数组作为函数的参数 2023/1/295 Program Design in C LanguagePage数组名作函数参数时应注意:数组名作函数参数时应注意:1 1)数数组组名名作作函函数数参参数数时时,应应在在主主调调函函数数和和被被调调函数中分别定义数组。函数中分别定义数组。2 2)实实参参数数组组与与形形参参数数组组的的类类型型必必须须相相同同,但但大大小可以不同。小可以不同。3 3)形参数组的一维下标可以省略。)形参数组的一维下标可以省略。4 4)数数组组名名表表示示的的是是数数组组元元素素的的首首地地址址,数数组组名名作作函函数数参参数数时时,传传递递的的是是整整个个数数组组。实实参参与与形形参之间的数据传递是参之间的数据传递是地址传递。地址传递。7.1.7 数组作为函数的参数 2023/1/296 Program Design in C LanguagePage数组名作函数的参数举例:数组名作函数的参数举例:7.1.7 数组作为函数的参数 2023/1/297 Program Design in C LanguagePage例例 利用数组换数利用数组换数 voidhuanshu2(intshuzu,intn);main()/*主函数主函数*/intab2=5,10,i;for(i=0;i2;i+)printf(1)ab%d=%2d,i,abi);huanshu2(ab,2);printf(n);for(i=0;i2;i+)printf(4)ab%d=%2d,i,abi);7.1.7 数组作为函数的参数 2023/1/298 Program Design in C LanguagePagevoidhuanshu2(intshuzu,intn)intt,i;printf(n);for(i=0;in;i+)printf(2)shuzu%d=%2d,i,shuzui);for(i=0;in-1;i+)t=shuzui;shuzui=shuzui+1;shuzui+1=t;printf(n);for(i=0;in;i+)printf(3)shuzu%d=%2d,i,shuzui);7.1.7 数组作为函数的参数 2023/1/299 Program Design in C LanguagePage说明:2000H A02002H A1ab=shuzu=2000H510105intab2=5,10;huanshu2(ab,2);for(i=0;i1从从以以上上定定义义看看,求求解解n!使使用用了了(n-1)!,也也即即要要计计算算n!,必必须须先先计计算算(n-1)!;要要计计算算(n-1)!,必必须须先先计计算算(n-2)!;依依次次类类推,直至推,直至1!=1.再以此为基础,返回来计算再以此为基础,返回来计算2!,3!,4!,.n!.7.2.2 函数的递归调用 2023/1/2920 Program Design in C LanguagePagefac(n)fac(n-1)fac(2)fac(1)fac(n-1)fac(n-2)fac(1)7.2.2 函数的递归调用 如果求数如果求数n的阶乘的函数名为的阶乘的函数名为fac(int),则有:,则有:2023/1/2921 Program Design in C LanguagePage例例使用递归算法编写计算使用递归算法编写计算n!的函数。的函数。longfac(intn)if(n=1)return1;elsereturnn*fac(n-1);voidmain()intm;scanf(%d,&m);printf(%2d!=%dn,m,fac(m);7.2.2 函数的递归调用 2023/1/2925 Program Design in C LanguagePage递递归归函函数数的的结结构构十十分分简简练练。构构造造递递归归函函数数的的关关键键是是找找到到适适当当的的递递归归算算法法和和终终结结条条件件。因因为为递递推推的的过过程程不不能能无无限限制制地地进进行行下下去去,必必须须要要有有一一个个结结束束此此过过程程的的条条件件。在在上上例例求求n!的的过过程程中中,1!=1就就是是这这样样的的结结束束递推过程的条件。递推过程的条件。递递归归函函数数最最典典型型的的例例子子是是Hanoi塔塔问问题题,它它能能较较好地显示出函数递归调用的作用好地显示出函数递归调用的作用.7.2.2 函数的递归调用 2023/1/2926 Program Design in C LanguagePage例例汉汉诺诺(Hanoi)塔塔问问题题是是一一个个古古老老的的数数学学问问题题:在在一一个个塔塔座座(设设为为塔塔1)上上有有若若干干片片盘盘片片,盘盘片片大大小小各各不不相相等等,按按大大盘盘在在下下、小小盘盘在在上上的的顺顺序序叠叠放放,现现要要将将其其移移放放至至另另一一个个塔塔座座(设设为为塔塔2)上上去去。问问:仅仅依依靠靠一一个个附附加加的的塔塔座座(设设为为塔塔3),在在每每次次仅仅只只能能搬搬动动一一片片盘盘片片,且且在在整整个个移移动动过过程程中中始始终终保保持持每每座座塔塔座座上上的的盘盘片片均均为为大大盘盘在在下下、小小盘盘在在上上的的叠叠放放方方式式,能能做做到到么?如何移法?么?如何移法?7.2.2 函数的递归调用 2023/1/2927 Program Design in C LanguagePage对对此此问问题题,一一个个想想法法是是采采用用递递归归的的方方法法。移移动动n个个圆盘可以看成由移动圆盘可以看成由移动n-1个圆盘来完成个圆盘来完成(这就是递归这就是递归)。(1)借助塔借助塔2,将,将n-1个圆盘从塔个圆盘从塔1移动了塔移动了塔3。(2)将最大的一片圆盘将最大的一片圆盘(第第n个圆盘个圆盘)从塔从塔1移动了塔移动了塔2。(3)借助塔借助塔1,将,将n-1个圆盘从塔个圆盘从塔3移动了塔移动了塔2。重重复复上上述述步步骤骤,直直到到完完成成最最后后一一个个操操作作“移移动动n=1个圆盘个圆盘”。7.2.2 函数的递归调用 2023/1/2928 Program Design in C LanguagePage对对于于数数量量不不等等的的圆圆盘盘(设设为为n片片),只只要要能能将将除除最最下下面面最最大大的的一一片片圆圆盘盘外外,其其余余的的盘盘片片(n-1片片)移移至至塔塔3座座上上,剩剩下下一一片片就就可可直直接接移移至至塔塔2上上。其其余余的的(n-1片片)盘盘片片既既能能从从塔塔1移移至至塔塔3,自自然然也也可可照照理理从从塔塔3移移至至塔塔2,问问题题就就解解决决了了。每每次次使使用用同同样样的的办办法法解解决决最最下下面面最最大大一一片片圆圆盘盘的的移移动动问问题题,一一次次次次搬搬下下去去,直直至至剩剩下下最最后后一一片圆盘,直接搬到塔片圆盘,直接搬到塔2上去就可以了。上去就可以了。7.2.2 函数的递归调用 2023/1/2929 Program Design in C LanguagePage这这个个想想法法是是成成立立的的,也也确确实实是是解解决决此此问问题题的的办办法法。这这是是典典型型的的递递归归问问题题,递递归归的的结结束束条条件件是是只只剩剩下下一片圆盘时,可直接移至目的座(塔一片圆盘时,可直接移至目的座(塔2)上。)上。下下面面是是解解决决汉汉诺诺塔塔的的程程序序,程程序序能能打打印印出出盘盘片片移移动动过过程程中中的的每每一一搬搬动动步步骤骤,塔塔座座1、2、3分分别别用用字字符符1、2、3表示。表示。“”表示搬动塔座最上面的一片盘片。表示搬动塔座最上面的一片盘片。7.2.2 函数的递归调用 2023/1/2933 Program Design in C LanguagePagevoid hanoi ta(int n,char ta1,char ta2,char ta3);/*函数函数原型原型*/main()int n;printf(“input the number of diskes:”)scanf(“%d”,&n);/*输入盘片数输入盘片数*/hanoi ta(n,1,2,3);7.2.2 函数的递归调用 2023/1/2934 Program Design in C LanguagePagevoid hanoi ta(int n,char ta1,char ta2,char ta3);if(n=1)printf(“%c%cn”,tal,ta2);/*一一片片盘盘时时,直接移动直接移动*/elsehanoi ta(n-1,ta1,ta3,ta2);/*n-1片盘由片盘由ta1座移至座移至ta3座座*/printf(“%c%cn”,ta1,ta2);/*最下面最大一片盘,直接移动最下面最大一片盘,直接移动*/hanoi ta(n-1,ta3,ta2,ta1);/*n-1片盘由片盘由ta3座移至座移至ta2座座*/7.2.2 函数的递归调用 2023/1/2935 Program Design in C LanguagePage例例使用递归算法求使用递归算法求m和和n的最大公约数的最大公约数gcd分析:求分析:求m和和n的最大公约数等价于求的最大公约数等价于求n与与(mmodn)的最大公约数。的最大公约数。则有则有gcd(m,n)等价于等价于gcd(n,(mmodn)例如:求例如:求24和和16的最大公约数的最大公约数即求与即求与gcd(16,(24mod16)的最大公约数的最大公约数为为gcd(16,8)又等价于又等价于gcd(8,(16mod8)为为gcd(8,0)此时此时n为零,为零,m即为最大公约数即为最大公约数7.2.2 函数的递归调用 2023/1/2936 Program Design in C LanguagePage#include#includevoidmain()floatgcd(),m,n,g;printf(“nInputm,n:n”);scanf(“%f,%f”,&m,&n);g=gcd(m,n);printf(“ngcd(%2.0f,%2.0f)=%5.0fn”,m,n,g);程序如下:程序如下:7.2.2 函数的递归调用 2023/1/2937 Program Design in C LanguagePagefloatgcd(a,b)floata,b;if(b=0)return(a);elsereturn(gcd(b,fmod(a,b);7.2.2 函数的递归调用 2023/1/2938 Program Design in C LanguagePage 变变量量的的作作用用范范围围也也称称变变量量的的作作用用域域,即变量可以存储或访问的范围。即变量可以存储或访问的范围。变量的作用域是指变量的变量的作用域是指变量的可见性可见性。变量的作用范围变量的作用范围7.3.1 变量的作用域 2023/1/2939 Program Design in C LanguagePage局部变量局部变量:在一个函数内部定义的变量。在一个函数内部定义的变量。局局部部变变量量的的作作用用范范围围仅仅限限于于本本函函数数,即即只只有有在在本函数内才能使用它们,其他函数不能使用它们。本函数内才能使用它们,其他函数不能使用它们。说明:说明:不不同同函函数数中中可可以以使使用用相相同同名名字字的的变变量量,它它们们代代表表不不同的对象,互不干扰。同的对象,互不干扰。形参也是局部变量。形参也是局部变量。可可以以在在一一个个复复合合语语句句中中定定义义变变量量,这这些些变变量量只只在在本本复合语句中有效。复合语句中有效。1、局部变量局部变量7.3.1 变量的作用域 2023/1/2940 Program Design in C LanguagePage局部变量举例main()int x,y;float f1,f2;hanshu(int x,float y)int a,b,c;7.3.1 变量的作用域 2023/1/2941 Program Design in C LanguagePage局部变量的使用局部变量的使用:说出下列程序的运行结果说出下列程序的运行结果#includevoidf2(intx,inty)x+;y+;voidf1(intx,inty)intn=0;f2(x,y);printf(n=%d,x=%d,y=%dn,n,x,y);7.3.1 变量的作用域 2023/1/2942 Program Design in C LanguagePagevoidmain()intn=2,a=3,b=4;f1(a,b);printf(n=%d,a=%d,b=%dn,n,a,b);n=0,x=3,y=4n=2,a=3,b=47.3.1 变量的作用域 2023/1/2943 Program Design in C LanguagePage全局变量:全局变量:在函数外定义的变量,也称外部变量。在函数外定义的变量,也称外部变量。作用范围作用范围:从从其其定定义义的的地地方方开开始始直直至至源源程程序序文文件件的的结结束束。全全局局变量通常放在源程序的开始处。变量通常放在源程序的开始处。全局变量命名时,首字母大写,其余字母小写。全局变量命名时,首字母大写,其余字母小写。2、全局变量全局变量7.3.1 变量的作用域 2023/1/2944 Program Design in C LanguagePage全局变量举例intAbc,D1;main()()floatf1,f2;floatKa,Hc;hanshu(intx,inty)doublec,e;全局变量Ka,Hc的作用域全局变量Abc,D1的作用域7.3.1 变量的作用域 2023/1/2945 Program Design in C LanguagePage例intX=3;intfunc()intc=0;c+=X;X+=10;return(c);main()intk=2;k=func();printf(1)%dn,k);k=func();printf(2)%dn,k);运行结果运行结果:1)32)137.3.1 变量的作用域 如何得出的如何得出的:1)c=0+3=3,X=3+10=132)c=0+13=13,X=13+10=232023/1/2946 Program Design in C LanguagePage全局变量的特点:优点优点:利用全局变量可以从函数中得到一个以上的返回值。利用全局变量可以从函数中得到一个以上的返回值。利用全局变量可以减少函数中实参和形参的个数。利用全局变量可以减少函数中实参和形参的个数。缺点:缺点:全全局局变变量量在在程程序序运运行行过过程程中中始始终终都都占占用用存存储储单单元元,而而不是在函数被调用时才临时分配存储单元。不是在函数被调用时才临时分配存储单元。函数的通用性降低。函数的通用性降低。在在同同一一个个源源程程序序中中,当当全全局局变变量量与与局局部部变变量量同同名名,在在局局部部变变量量的的作作用用域域内内,全全局局变变量量不不起起作作用用,即即全全局局变变量被量被屏蔽屏蔽。7.3.1 变量的作用域 2023/1/2947 Program Design in C LanguagePage例intM=5;intfun(intx,inty)intM=10;return(x*y-M);main()inta=7,b=5;printf(%dn,fun(a,b)/M);运行结果运行结果:57.3.1 变量的作用域 2023/1/2948 Program Design in C LanguagePage例例已知一个一维数组,用一个函数求数组最大已知一个一维数组,用一个函数求数组最大数、最小数和平均数。数、最小数和平均数。#includeintNum,Max,Min;intaverage(intarray)inti;intarray_aver=array0;Max=Min=array0;for(i=1;iMax)Max=arrayi;if(arrayiMin)Min=arrayi;7.3.1 变量的作用域 2023/1/2949 Program Design in C LanguagePagearray_aver+=arrayi;array_aver/=Num;returnarray_aver;voidmain()intaver,n5=23,2,4,5,6;Num=5;aver=average(n);printf(max=%d,min=%d,average=%dn,Max,Min,aver);7.3.1 变量的作用域 2023/1/2950 Program Design in C LanguagePagefunc(inta,intb)intm=0,i=2;i+=m+1;m=i+a+b;returnm;main()intk=4,m=1,p;p=func(k,m);printf(“p=%dn”,p);p=func(k,m);printf(“p=%dn”,p);求求程程序序运运行行结结果果程序运行结果:程序运行结果:p=8p=8函数练习题:函数练习题:程序运行过程:程序运行过程:func(4,1)i=3,m=3+4+1=82023/1/2951 Program Design in C LanguagePage1、编写一个计算字符串长度的、编写一个计算字符串长度的递归递归函数。函数。要求:输入一个任意长度的字符串,输要求:输入一个任意长度的字符串,输出该串的长度。出该串的长度。函数练习题:函数练习题:2023/1/2952 Program Design in C LanguagePage程序:程序:#includeinti=0;main()intstlen();charstr100;printf(Inputstring:n);gets(str);strlen(str);printf(Thestringlength=%dn,i);intstlen(s)chars;if(si=0)return(i);elsei+;strlen(s+);函数练习题:函数练习题:2023/1/2953 Program Design in C LanguagePage有以下函数定义:有以下函数定义:voidfun(intn,doublex)若以下选若以下选项中的变量都已正确定义并赋值,则对函项中的变量都已正确定义并赋值,则对函数数fun的正确调用语句是的正确调用语句是_。A.fun(intx,doublen);B.m=fun(10,12.5);C.fun(x,n);D.voidfun(n,x);函数练习题:函数练习题:2023/1/2954 Program Design in C LanguagePage下面函数下面函数f(doublex)printf(“%6dn”,x);的类型为的类型为_。A.实型实型B.void类型类型C.int类型类型D.A、B、C均不正确均不正确函数练习题:函数练习题:2023/1/2955 Program Design in C LanguagePage在函数调用过程中,如果函数在函数调用过程中,如果函数A调用了函数调用了函数B,函数函数B又调用了函数又调用了函数A,则,则_。A.称为函数的直接递归调用称为函数的直接递归调用B.称为函数称为函数的间接递归调用的间接递归调用C.称为函数的循环调用称为函数的循环调用D.C语言中不允语言中不允许这样的递归调用许这样的递归调用函数练习题:函数练习题:2023/1/2956 Program Design in C LanguagePage有以下程序:有以下程序:#includefloatfun(intx,inty)return(x+y);main()inta=2,b=5,c=8;printf(%3.0fn,fun(int)fun(a+b,b),a-c);return;程序运行结果为程序运行结果为_。A.9.0B.21C.6D.编译出错编译出错函数练习题:函数练习题:2023/1/2957 Program Design in C LanguagePage已有数组定义已有数组定义inta34;和函数调用语句和函数调用语句f(a);,则,则在在f函数的说明中,对形参数组函数的说明中,对形参数组array的错误定义方的错误定义方式是式是_。A.f(intarray6)B.f(intarray3)C.f(intarray4)D.f(intarray25)在一个源文件中定义的全局变量的作用域为在一个源文件中定义的全局变量的作用域为_。A.本文件的全部范围。本文件的全部范围。B.本程序的全部范围。本程序的全部范围。C.本函数的全部范围。本函数的全部范围。D.从定义该变量的位置开始至本文件结束。从定义该变量的位置开始至本文件结束。函数练习题:函数练习题:2023/1/2958 Program Design in C LanguagePage下列说法中正确的是下列说法中正确的是_。A.调用函数时,实参变量与形参变量可以共用内存调用函数时,实参变量与形参变量可以共用内存单元。单元。B.调用函数时,实参的个数、类型和顺序与形参可调用函数时,实参的个数、类型和顺序与形参可以不一致。以不一致。C.调用函数时,形参可以是表达式。调用函数时,形参可以是表达式。D.调用函数时,将为形参分配内存单元。调用函数时,将为形参分配内存单元。函数练习题:函数练习题:2023/1/2959 Program Design in C LanguagePage以下叙述中不正确的是以下叙述中不正确的是_。A.在不同的函数中可以使用相同名字的变量。在不同的函数中可以使用相同名字的变量。B.函数中的形式参数是局部变量。函数中的形式参数是局部变量。C.在一个函数内定义的变量只在本函数范围内有效。在一个函数内定义的变量只在本函数范围内有效。D.在一个函数内的复合语句中定义的变量在本函数在一个函数内的复合语句中定义的变量在本函数范围内有效。范围内有效。函数练习题:函数练习题:2023/1/2960 Program Design in C LanguagePage函数调用语句函数调用语句f(x,y),(a,b,c),(1,2,3,4);中,所含的实中,所含的实参个数是参个数是_。A.1B.2 C.3 D.4用数组名作为函数调用时的实参,实际上传递给形用数组名作为函数调用时的实参,实际上传递给形参的是参的是_。A.数组的首地址数组的首地址 B.数组的第一个元素的值数组的第一个元素的值C.每一个数组元素每一个数组元素D.数组元素的个数数组元素的个数函数练习题:函数练习题:2023/1/2961 Program Design in C LanguagePage以下程序的输出结果是以下程序的输出结果是_。#includeintpower(intx,inty);main()floata=2.6,b=3.4;intp;p=power(int)a,(int)b);printf(%dn,p);return;intpower(intx,inty)inti,p=1;for(i=y;i0;i-)p=p*x;returnp;A.8 B.9 C.27D.81函数练习题:函数练习题:2023/1/2962 Program Design in C LanguagePage程序的运行结果为程序的运行结果为:#includevoidsort(inta,intn)inti,j,t;for(i=0;in-1;i+=2)for(j=i+2;jn;j+=2)if(aiaj)t=ai;ai=aj;aj=t;main()intaa10=1,2,3,4,5,6,7,8,9,10,i;sort(aa,10);for(i=0;i10;i+)printf(%d,aai);printf(n);return;函数练习题:函数练习题:2023/1/2963 Program Design in C LanguagePage1 1、写一个函数求、写一个函数求Fibonacci(Fibonacci(斐波拉契斐波拉契)数列前数列前2020项。项。该数列第一项为该数列第一项为1 1,第二项为,第二项为1 1,从第三项起为前两,从第三项起为前两项的和。项的和。1 1 2 3 5 1 1 2 3 5 上机实验内容上机实验内容2 2、用递归算法编程计算、用递归算法编程计算FibonacciFibonacci数列的数列的前前2020项。项。2023/1/2964 Program Design in C LanguagePage1 1、写一个函数求、写一个函数求Fibonacci(Fibonacci(斐波拉契斐波拉契)数列前数列前2020项。项。该数列第一项为该数列第一项为1 1,第二项为,第二项为1 1,从第三项起为前两,从第三项起为前两项的和。项的和。1 1 2 3 5 1 1 2 3 5 2023/1/2965 Program Design in C LanguagePage#includevoidfib(intf,intn)inti;intf20=1,1;for(i=2;in;i+)fi=fi-2+fi-1;for(i=0;in;i+)if(i%5=0)printf(n);printf(%12d,fi);main()fib(fi,20);2023/1/2966 Program Design in C LanguagePage2 2、用递归算法编程计算、用递归算法编程计算FibonacciFibonacci数列的数列的前前2020项。项。2023/1/2967 Program Design in C LanguagePage#includeintfib(intn)if(n=2)return(fib(n-1)+fib(n-2);elsereturn(1);main()inti;intf20=1,1;for(i=2;i20;i+)fi=fib(i);for(i=0;i20;i+)if(i%5=0)printf(n);printf(%12d,fi);2023/1/2968 Program Design in C LanguagePage1 1、写一个程序,从键盘输入写一个程序,从键盘输入 2 2个正整数,然后求出个正整数,然后求出它们的最小公倍数,并显示输出(通过调用对两个它们的最小公倍数,并显示输出(通过调用对两个正整数求最小公倍数的函数实现)。正整数求最小公倍数的函数实现)。上机实验内容上机实验内容2023/1/2969 Program Design in C LanguagePage上机实验内容上机实验内容main()intb5,i,f5;for(i=0;i=0;i-)fi-1=hef(fi,bi-1);printf(%d,f0);