1上讲回顾结构化程序设计的思想及方法;函数的原型声明;函数的定义;函数的形参、实参;函数调用;2本讲要点函数的嵌套;函数的递归调用;局部变量、全局变量;变量的存储类别;3函数的嵌套调用函数的定义互相平行、独立。在定义函数时,一个函数内不能包括另一个函数的定义。即函数不能嵌套定义!如以下形式:…main(){…}intA(…)//函数A的定义{…intB(…)//函数B的定义{…}}•函数不可以嵌套定义,即在定义一个函数的时候,不能同时再定义另一个函数!×4函数的嵌套函数可以嵌套调用,即在定义一个函数时,可以在函数体中调用另外的函数;5//例从键盘输入三个数,求它们中最大数和最小数的差#includestdio.hvoidmain(){int_max(int,int,int);//原型声明int_min(int,int,int);int_dif(int,int,int);intx,y,z;scanf(%d,%d,%d,&x,&y,&z);printf(%d\n,_dif(x,y,z));}int_max(inta,intb,intc){//求三个数的最大值intmax;max=ab?a:b;max=maxc?max:c;returnmax;}(接右上)int_min(inta,intb,intc){//求三个数的最小值intmin;min=ab?b:a;min=minc?c:min;returnmin;}int_dif(inta,intb,intc){//求三个数最大值、最小值之差return_max(a,b,c)-_min(a,b,c);}•函数的嵌套调用:在自定义函数_dif()定义的过程中调用了自定义函数_max()和_min();6函数的递归调用递归调用:在调用一个函数的过程中又出现了直接或者间接的调用该函数本身。直接调用:在调用某一函数A时,又出现了嵌套调用该函数本身的情况;(较常见)间接调用:在调用某一函数A的过程中,嵌套调用了另一函数B,在函数B中,又出现了调用函数A的情况;7例:求n!非递归#includestdio.hvoidmain(){intn,i,p=1;scanf(%d,&n);//本例未对n的有效性进行判断for(i=1;i=n;i++)p*=i;printf(%d\n,p);}8递归求解分析:n=0其阶乘p=0!=1;n=1其阶乘p=1!=1;n=2其阶乘p=2!=1!*2=2;n=3其阶乘p=3!=2!*3=6;…1n=0,1n!=n*(n-1)!n19分析如果自定义一个函数fac()来求阶乘,那么fac(n)=fac(n-1)*n,在求n的阶乘时要调用自身函数,即存在递归(直接调用)。10自定义求阶乘的函数fac()floatfac(intn){//自定义fac函数求n的阶乘floatf;if(n0)printf(“Error!\n”);//x0时,数据无效;elseif(n==0||n==1)f=1;//0or1的阶乘为1;elsef=fac(n-1)*n;//n的阶乘等于n-1的阶乘乘n;returnf;//返回n的阶乘值}•在fac函数中出现了调用自身的情况,(直接调用)---递归调用11//完整的递归调用求n!源程序#includestdio.hvoidmain(){floatfac(int);//原型声明intn;floatf;printf(pleaseinputthedata:\n);scanf(%d,&n);f=fac(n);printf(%f\n,f);}floatfac(intn){//自定义fac函数求n的阶乘floatf;if(n0)printf(Error!\n);//x0时,数据无效;elseif(n==0||n==1)f=1;//0or1的阶乘为1;elsef=fac(n-1)*n;//n的阶乘等于n-1的阶乘乘n;returnf;//返回n的阶乘值}12#includestdio.hvoidmain(){floatfac(int);//原型声明intn;floatf;printf(pleaseinputthedata:\n);scanf(%d,&n);f=fac(n);printf(%f\n,f);}floatfac(intn){//自定义fac函数求n的阶乘floatf;if(n0)printf(Error!\n);//x0时,数据无效;elseif(n==0||n==1)f=1;//0or1的阶乘为1;elsef=fac(n-1)*n;//n的阶乘等于n-1的阶乘乘n;returnf;//返回n的阶乘值}问题:两个函数中都有n,f变量,为什么编译时没有报错,提示变量重复定义?13变量的作用域变量的作用域:变量的作用范围,即变量有效的范围。变量的分类从作用域分,可分为局部变量,外部变量(又称为全局变量or全程变量)局部变量---在函数内部定义的变量;它只在本函数内有效,即只在本函数内才能使用它们;其作用域只限于从定义的位置到本函数结束。外部变量---在函数之外定义的变量;它可被源程序中其他函数所共用;其作用域从变量定义的位置到源程序结束。14#includestdio.hvoidmain(){floatfac(int);//原型声明intn;floatf;printf(pleaseinputthedata:\n);scanf(%d,&n);f=fac(n);printf(%f\n,f);}floatfac(intn){//自定义fac函数求n的阶乘floatf;if(n0)printf(Error!\n);//x0时,数据无效;elseif(n==0||n==1)f=1;//0or1的阶乘为1;elsef=fac(n-1)*n;//n的阶乘等于n-1的阶乘乘n;returnf;//返回n的阶乘值}n为局部变量f为局部变量n作用范围f作用范围•分析一下,在fac函数中n,f分别都是什么变量,他们的作用范围分别是什么?15关于全局变量说明设置全局变量增加了函数间数据联系的渠道,因为全局变量可以被同一源程序中的所有函数所共用,如果在一个函数中其值发生改变,会影响到其他函数。不在必要的情况下不要使用全局变量P186全局变量在程序执行的全部过程中都占用存储单元;降低了函数的通用性;降低程序的清晰性;16关于全局变量说明(续)如果在同一源程序中,外部变量与局部变量同名,则在局部变量的作用域内,外部变量被“屏蔽”,即它不起作用。例:#includestdio.hinta=3;//定义外部变量avoidmain(){inta=8;//定义局部变量aprintf(%d,a);}程序的运行结果是8而不是3,此时外部变量被“屏蔽”17例:以下程序的输出结果是?#includestdio.hvoidmain(){intfac(int);inti;for(i=1;i=5;i++)printf(%d!=%d\n,i,fac(i));}intfac(intn){staticintf=1;f*=n;returnf;}1!=12!=23!=64!=245!=12018#includestdio.hvoidmain(){intfac(int);inti;for(i=1;i=5;i++)printf(%d!=%d\n,i,fac(i));}intfac(intn){staticintf=1;f*=n;returnf;}•static静态变量:静态局部变量、静态外部变量•静态局部变量的值在函数调用结束后不消失而保留原值,其所占用的内存单元不释放,在下一次该函数被调用时,该变量的值是上一次函数调用结束时的值;•对于静态局部变量,如果定义时不赋初值,则编译时系统自动赋初值为0;•虽然静态局部变量在函数调用结束后仍然存在,但其他函数不能引用;•静态存储变量长期占用内存,易浪费资源,且降低了程序的可读性,若非必要,不易多用!•说明:•自己阅读教材P188~19719作业结合第7、8讲课件阅读教材:8.1~8.6节,认真书写自己的阅读总结及认识体会;(重点掌握)阅读教材8.8~8.9。(了解、掌握变量的作用域和存储类别)20习题讲解8.1#includestdio.hvoidmain(){intgongyue(int,int);intgongbei(int,int,int);intm,n,t;scanf(%d,%d,&m,&n);if(mn){inttemp;temp=m;m=n;n=temp;}t=gongyue(m,n);printf(最大公约数是%d\n,t);printf(最小公倍数是%d\n,gongbei(m,n,t));}//后接右上intgongyue(intx,inty){inti,max;for(i=1;i=x;i++)if(x%i==0&&y%i==0)max=i;returnmax;}intgongbei(intx,inty,intz){returnx*y/z;}21习题讲解8.3#includestdio.hvoidmain(){intprime(int);intm;scanf(%d,&m);if(prime(m))printf(是一个素数\n);elseprintf(不是一个素数\n);}//接右上intprime(intn){inti,flag=1;if(n=0||n==1){flag=0;}for(i=2;in/2;i++)if(n%i==0){flag=0;break;}elsecontinue;returnflag;}