资源预览内容
第1页 / 共66页
第2页 / 共66页
第3页 / 共66页
第4页 / 共66页
第5页 / 共66页
第6页 / 共66页
第7页 / 共66页
第8页 / 共66页
第9页 / 共66页
第10页 / 共66页
亲,该文档总共66页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述
1第第七七章章 函函数数7.1 7.1 函函数数概概述述7.2 7.2 函函数数定定义义和和调调用用7.3 7.3 函函数数调调用用中中的的参参数数传传递递7.4 7.4 函函数数的的嵌嵌套套调调用用和和递递归归调调用用7.5 7.5 函函数数的的返返回回值值为为指指针针7.6 7.6 变变量量的的作作用用域域和和存存储储类类别别7.7 7.7 内内部部函函数数和和外外部部函函数数 2函函数数是是构构成成C C程程序序的的基基本本构构件件。C C语语言言的的程程序序是是由由一一个个主主函函数数或或若若干干个个函函数数组组成成的的。但但编编译译单单位位是是源源程程序序文文件件,而而不不是是函函数数。C C程程序序执执行行是是从从mainmain函函数数(主主函函数数)开开始始,在在mainmain函函数数中中结结束束,不不管管mainmain函函数数的的位位置置如如何何。所所有有的的函函数数独独立立定定义义,main( )main( )函函数数可可以以调调用用任任意意其其它它函函数数,其其它它函函数数之之间间可可以以相相互互调调用用,但但任任何何函函数数都都不不能能调调用用main( )main( )函函数数。7.1 7.1 函函数数概概述述3函函数数的的分分类类库库函函数数:由由系系统统提提供供,供供用用户户直直接接调调用用自自定定义义函函数数:由由程程序序员员自自己己定定义义,解解决决特特定定的的问问题题有有参参函函数数:函函数数带带有有参参数数(自自变变量量)如如sqrt(x)、printf(y=%dn,y)无无参参函函数数:函函数数无无参参数数如如getchar()、rand()有有返返回回值值函函数数:函函数数被被调调用用后后返返回回一一个个值值如如sin(x)、getchar()无无返返回回值值函函数数:函函数数被被调调用用后后无无返返回回值值如如clrscr()4 如如: g(g(x,yx,y)= )= g(g(3,43,4)= = )= = 5 5函函数数定定义义函函数数调调用用两两个个形形式式参参数数两两个个实实际际参参数数函函数数值值7.2 7.2 函函数数的的定定义义与与调调用用函函数数定定义义时时函函数数名名后后的的括括号号中中的的变变量量叫叫形形式式参参数数,简简称称形形参参函函数数调调用用时时函函数数名名后后的的括括号号中中的的参参数数叫叫实实际际参参数数,简简称称实实参参5一一、函函数数定定义义与与调调用用的的一一般般形形式式l函函数数定定义义的的格格式式:函函数数类类型型名名函函数数名名(形形参参及及形形参参声声明明表表)内内部部变变量量定定义义和和声声明明部部分分执执行行语语句句l函函数数定定义义后后,并并不不被被执执行行,只只有有当当调调用用函函数数时时,程程序序才才转转到到函函数数去去执执行行。l函函数数调调用用的的格格式式: 函函数数名名(实实参参表表)6#include(一一)无无参参无无返返回回值值函函数数的的定定义义与与调调用用voidpstar()printf(*n);/*输输出出一一行行20个个*号号*/voidmain()inti;for(i=1;i=10;i+)pstar();函函数数类类型型void(“空空类类型型”)表表示示无无返返回回值值无无参参数数以以语语句句方方式式调调用用无无返返回回值值函函数数函函数数定定义义函函数数名名函函数数体体7#include体体内内变变量量定定义义,形形参参在在体体内内不不能能再再定定义义(二二)有有参参无无返返回回值值函函数数的的定定义义与与调调用用形形参参n定定义义为为int型型函函数数定定义义实实参参20voidpstar(intn)inti;for(i=1;i=n;i+)printf(*);printf(n);voidmain()inti;for(i=1;i=10;i+)pstar(20);若若实实参参改改为为i,程程序序输输出出结结果果又又是是什什么么?8#include (三三)有有返返回回值值函函数数的的定定义义与与调调用用intmax(intx,inty)intz;z=xy?x:y;return(z);voidmain()inta,b,c;scanf(%d%d,&a,&b);c=max(a,b);printf(maxis%dn,c);函函数数定定义义return后后z的的值值作作为为函函数数返返回回值值returnz;return(xy?x:y);int型型函函数数(int 可可缺缺省省),表表示示函函数数返返回回值值为为整整型型max函函数数带带回回返返回回值值并并赋赋给给creturn后后的的括括号号可可以以不不要要return后后可可以以是是一一个个表表达达式式例例7.5有有参参有有返返回回值值/*或或returnxy?x:y;*/不不能能写写为为intx,y;9有有返返回回值值函函数数的的定定义义与与调调用用intmax(intx,inty)return(xy?x:y);voidmain()inta,b;scanf(%d%d,&a,&b);printf(maxis%dn,max(a,b);函函数数定定义义将将max函函数数的的返返回回值值作作为为printf函函数数的的参参数数#include10l函函数数返返回回值值通通过过returnreturn语语句句获获得得: return (return (表表达达式式) ); 或或 return return 表表达达式式; l一一个个函函数数只只能能返返回回一一个个确确定定的的值值。 return a,b; return a,b; 表表示示返返回回逗逗号号表表达达式式(a,b)(a,b)的的值值。l一一个个函函数数可可以以有有多多个个returnreturn语语句句,即即多多个个出出口口。二二、函函数数的的返返回回值值 P202intmax(intx,inty)if(xy)returnx;elsereturny;11l函函数数返返回回值值的的类类型型:取取决决于于函函数数的的类类型型。函函数数的的返返回回值值l一一个个函函数数若若没没有有返返回回值值,函函数数体体内内无无需需returnreturn语语句句,或或returnreturn后后面面不不跟跟表表达达式式。 将将无无返返回回值值的的函函数数类类型型定定义义为为voidvoid。intmax(floatx,floaty)floatz;z=xy?x:y;return(z);函函数数返返回回值值是是float还还是是int型型?int例例7.612三三、函函数数调调用用的的方方式式 P200函函数数调调用用的的格格式式:函函数数名名(实实参参表表)l函函数数语语句句方方式式:把把函函数数调调用用作作为为一一个个语语句句,这这种种调调用用方方式式不不要要求求函函数数有有返返回回值值,或或不不使使用用函函数数的的返返回回值值。如如,pstar(20)pstar(20); printf(Helloprintf(Hello!);!);l函函数数表表达达式式方方式式:函函数数调调用用出出现现在在表表达达式式中中,这这种种调调用用方方式式要要求求函函数数返返回回一一个个确确定定的的值值以以参参加加表表达达式式的的运运算算。如如,c=max(a,b);y y=2*sin(x);l函函数数参参数数方方式式:把把函函数数调调用用作作为为一一个个实实参参进进行行函函数数调调用用,这这种种调调用用方方式式也也要要使使用用函函数数的的返返回回函函数数值值。如如,printf(maxis%dn,max(a,b);13举举例例 判判断断素素数数函函数数1(无无返返回回值值函函数数)prime(intm)intj,k;k=sqrt(m);for(j=2;jk)printf(%disaprimenumbern,m);elseprintf(%disnotaprimenumbern,m);main()intn;scanf(%d,&n);prime(n);voidprime(intm)为为了了明明确确表表示示“不不带带回回值值”,用用void定定义义函函数数类类型型#include#include14举举例例 判判断断素素数数函函数数2(有有返返回回值值函函数数)#include#includevoidmain()intn;scanf(%d,&n);f=1;f=0;return(f);if()printf(%disaprimenumbern,n);elseprintf(%disnotaprimenumbern,n);(prime(n)=1)(prime(n)intprime(intm)intj,k,f;k=sqrt(m);/*f标标识识是是否否为为素素数数*/for(j=2;jk)else/*返返回回1表表示示m是是素素数数,返返回回0表表示示m不不是是素素数数*/prime(intm)函函数数返返回回值值类类型型为为int时时,int可可缺缺省省15四四、函函数数调调用用的的条条件件 P2051 1、被被调调函函数数是是库库函函数数或或已已经经存存在在的的自自定定义义函函数数。2 2、若若被被调调函函数数是是库库函函数数,需需在在文文件件开开头头将将其其头头文文件件#include#include到到本本文文件件。 TC2.0TC2.0例例外外:调调用用scanfscanf函函数数和和printfprintf函函数数时时,可可缺缺省省 #include #include 3 3、若若被被调调函函数数是是自自定定义义函函数数,一一般般应应在在调调用用前前进进行行函函数数原原型型声声明明,声声明明的的格格式式是是: 函函数数类类型型名名 函函数数名名( (形形参参名名及及其其类类型型表表);); 或或者者:函函数数类类型型名名 函函数数名名( (形形参参类类型型表表) ); 举举例例:int int max(intmax(int x,intx,int y); y); 或或 int int max(int,intmax(int,int);); 例例外外:若若被被调调函函数数定定义义在在前前、调调用用在在后后,则则可可不不加加函函数数原原型型声声明明。16函函数数原原型型声声明明方方式式1 1、在在主主调调函函数数内内部部声声明明;2 2、在在函函数数的的外外部部声声明明,一一般般放放在在所所有有函函数数定定义义之之前前,即即文文件件开开头头。17函函数数原原型型声声明明举举例例#includevoidmain()floata,b,c;scanf(%f,%f,&a,&b);c=sub(a,b);printf(“subis%fn,c);floatsub(floatx,floaty)floatz;z=x-y;return(z);floatsub(floatx,floaty);函函数数的的调调用用和和声声明明的的格格式式有有什什么么区区别别?函函数数定定义义在在后后函函数数调调用用在在前前在在执执行行语语句句之之前前对对原原型型函函数数声声明明例例7.818五五、形形式式参参数数与与实实际际参参数数 P201l对对无无参参函函数数,形形参参表表列列与与实实参参表表列列均均为为空空,但但括括号号不不能能省省略略,如如fun( )fun( )。l对对有有参参函函数数,实实参参与与形形参参应应个个数数相相等等,顺顺序序对对应应,类类型型一一致致或或赋赋值值相相容容。l实实参参可可以以是是常常量量、变变量量或或表表达达式式。如如函函数数原原型型: : intmax(intx,inty);函函数数调调用用: : max(3,x1+5)max(ai,bi)数数组组元元素素ai,bi也也是是变变量量19形形式式参参数数与与实实际际参参数数 P201实实参参的的值值传传递递给给形形参参,而而形形参参的的值值不不会会传传回回给给实实参参,即即改改变变形形参参的的值值不不会会使使实实参参的的值值发发生生变变化化。l C语语言言实实参参与与形形参参相相互互作作用用的的特特点点:单单向向值值传传递递实实参参形形参参值值“值值传传递递”又又分分为为“数数值值传传递递”和和“地地址址传传递递”两两种种20intmult(intn)n*=10;return(n);voidmain()intnumber,result;number=668;result=mult(number);printf(result=%dn,result);printf(number=%dn,number);#include例例7.97.3 7.3 函函数数调调用用中中的的参参数数传传递递7.3.1 简简单单变变量量作作函函数数参参数数形形参参n n在在multmult函函数数定定义义时时指指定定,但但multmult函函数数未未被被调调用用时时,n n不不占占存存储储单单元元:调调用用前前:n未未分分配配,当当执执行行到到函函数数调调用用语语句句时时,才才给给形形参参n n分分配配存存储储单单元元,并并将将实实参参numbernumber的的值值传传递递给给形形参参:nnumber668668调调用用时时:number66821intmult(intn)n*=10;return(n);voidmain()intnumber,result;number=668;result=mult(number);printf(result=%dn,result);printf(number=%dn,number);#include例例7.9multmult函函数数调调用用中中,n n的的值值发发生生变变化化:调调用用中中:668 nmultmult函函数数调调用用结结束束,形形参参n n所所占占用用存存储储单单元元被被释释放放,实实参参numbernumber值值不不变变:调调用用后后:n被被释释放放number668实实参参简简单单形形参参数数值值单单向向数数值值传传递递6680number66822举举例例 写写函函数数对对两两个个数数按按降降序序排排列列(1)swap(intx,inty)intt;t=x;x=y;y=t;#includevoidmain()inta,b;scanf(%d,%d”,&a,&b);/*假假设设读读入入5和和9*/if(ab)swap(a,b);printf(%d,%dn,a,b);以以下下程程序序能能实实现现a和和b两两个个变变量量的的交交换换吗吗?a ab b5 59 9调调用用前前a ab b5 59 9x xy y5 59 9调调用用时时 t tx xy y9 95 55 5a ab b5 59 9调调用用中中 调调用用后后a ab b5 59 9改改变变形形参参变变量量的的值值无无法法实实现现a a和和b b两两个个变变量量的的交交换换!23指指针针类类型型实实参参指指针针类类型型形形参参地地址址值值7.3.2 指指针针变变量量作作函函数数参参数数单单向向地地址址传传递递实实参参形形参参值值单单向向值值传传递递若若指指针针作作为为函函数数参参数数:24swap(int*p1,int*p2)int*t;/*不不能能用用intt;*/t=p1;p1=p2;p2=t;#includevoidmain()inta,b;int*pointer1,*pointer2;scanf(%d,%d,&a,&b);pointer1=&a;pointer2=&b;if(ab)swap(pointer1,pointer2);printf(%d,%dn,a,b);p1p1p2p22000200020022002 举举例例 写写函函数数对对两两个个数数按按降降序序排排列列(2)20002000200220025 59 9a ab b2000200020022002pointer1pointer1pointer2pointer2例例7.12调调用用前前调调用用时时调调用用中中 t t200220022000200020002000改改变变形形参参指指针针的的值值无无法法实实现现a a和和b b两两个个变变量量的的交交换换!25swap(int*p1,int*p2)intt;/*不不能能用用int*t;*/t=*p1;*p1=*p2;*p2=t;#includevoidmain()inta,b;int*pointer1,*pointer2;scanf(%d,%d,&a,&b);pointer1=&a;pointer2=&b;if(ab)swap(pointer1,pointer2);printf(%d,%dn,a,b);p1p1p2p22000200020022002 举举例例 写写函函数数对对两两个个数数按按降降序序排排列列(3)20002000200220025 59 9a ab b2000200020022002pointer1pointer1pointer2pointer2例例7.11调调用用前前调调用用时时调调用用中中p1p1p2p220002000200220029 95 55 5 t t改改变变形形参参指指针针所所指指单单元元的的值值才才能能实实现现a a和和b b两两个个变变量量的的交交换换!26指指针针变变量量作作函函数数参参数数小小结结欲欲通通过过函函数数调调用用得得到到 n n个个要要改改变变的的值值,方方法法:1.1.主主调调函函数数:设设置置n n个个简简单单变变量量a1,a2,a1,a2,分分别别存存放放n n个个要要改改变变的的值值;2.2.被被调调函函数数:设设置置n n个个指指针针变变量量p1,p2,p1,p2,作作为为形形参参,函函数数体体改改变变* *p1,*p2,p1,*p2,的的值值;3.3.函函数数调调用用:主主调调函函数数以以a1,a2, a1,a2, 的的地地址址为为实实参参,于于是是形形参参p1,p2,p1,p2,指指向向a1,a2, a1,a2, ,被被调调函函数数改改变变 * *p1,*p2, p1,*p2, 的的值值实实际际上上就就是是改改变变a1,a2,a1,a2,的的值值。因因此此,函函数数调调用用结结束束,主主调调函函数数得得到到改改变变了了的的值值。27#includevoidfun(int*p,int*q)printf(%d%d,*p,*q);*p=7;*q=8;voidmain()intx=55,y=66;fun(&y,&x);printf(%d%dn,x,y);指指针针变变量量作作函函数数参参数数举举例例运运行行结结果果: :665587 665587 287.3.3 数数组组作作函函数数参参数数l 数数组组元元素素作作函函数数参参数数 - - 等等同同于于简简单单变变量量作作函函数数参参数数, 单单向向数数值值传传递递l 数数组组名名作作函函数数参参数数 - - 等等同同于于指指针针变变量量作作函函数数参参数数 单单向向地地址址传传递递29一一、数数组组元元素素作作函函数数参参数数举举例例 判判断断两两个个数数值值型型数数组组的的大大小小例例7.15:对对应应数数组组元元素素逐逐个个比比较较,如如果果数数组组a中中的的元元素素比比数数组组b中中元元素素大大的的次次数数多多,则则数数组组a大大于于数数组组b,反反之之数数组组b大大于于数数组组a,如如果果两两数数组组元元素素大大于于对对方方的的元元素素次次数数相相等等,则则两两数数组组相相等等。通通过过调调用用large函函数数实实现现函函数数large()的的功功能能:判判断断形形参参x、y的的大大小小,返返回回1、0、-1三三种种函函数数值值large( int x , int y )int flag ; if ( xy ) flag = 1 ; else if (x=y ) flag = 0 ; else flag = -1 ; return ( flag ) ; 30#includevoidmain()inta10,b10,i,n=0,k=0;for(i=0;i10;i+)scanf(%d,&ai);for(i=0;i10;i+)scanf(%d,&bi);for(i=0;ibi的的次次数数*/elseif(large(ai,bi)=-1)k+;/*累累计计aik)printf(arrayaislargerthanarraybn);elseif(nk)printf(arraybislargerthanarrayan);elseprintf(arrayaisequaltoarraybn);例例7.15 主主函函数数数数组组元元素素ai、bi作作实实参参31二二、一一维维数数组组名名作作函函数数参参数数 P216形形参参一一维维数数组组名名指指针针变变量量数数组组名名形形参参实实质质是是指指针针变变量量,接接收收实实参参传传递递的的数数组组首首地地址址。实实参参数数组组首首地地址址形形参参数数组组名名或或指指针针变变量量地地址址等等同同voidfun(intx6)voidmain()inta6;fun(a);实实参参a a形形参参x x aint*x注注意意:形形参参是是数数组组名名x x, 而而不不是是x6!x6!32l实实参参数数组组与与形形参参数数组组类类型型要要一一致致。l定定义义函函数数时时,形形参参数数组组不不占占存存储储单单元元; 发发生生函函数数调调用用时时,实实参参数数组组名名传传数数组组的的首首地地址址给给形形参参数数组组名名,于于是是形形参参数数组组结结合合到到实实参参数数组组所所占占用用的的存存储储空空间间。效效果果:函函数数调调用用期期间间,形形参参数数组组就就是是实实参参数数组组。对对形形参参数数组组的的操操作作,也也就就是是对对实实参参数数组组的的操操作作。一一维维数数组组名名作作函函数数参参数数实实参参a a形形参参x x a调调用用时时33一一维维数数组组名名作作函函数数参参数数形形参参一一维维数数组组名名指指针针变变量量实实参参一一维维数数组组名名 指指向向一一维维数数组组的的指指针针变变量量实实参参数数组组首首地地址址形形参参数数组组名名或或指指针针变变量量地地址址等等同同等等效效种种等等价价形形式式:(1)形形参参、实实参参都都用用数数组组名名(2)形形参参、实实参参都都用用指指针针变变量量(3)形形参参用用指指针针变变量量、实实参参用用数数组组名名(4)形形参参用用数数组组名名、实实参参用用指指针针变变量量34intsolve(intb10)intsum=0,i;for(i=0;i10;i+)if(bi!=0)sum+;return(sum);voidmain()inta10,num,i;for(i=0;i10;i+)scanf(%d,&ai);num=solve(a);printf(num=%dn,num);intb)只只能能在在实实参参数数组组大大小小范范围围内内使使用用形形参参数数组组#include举举例例 编编写写函函数数统统计计一一维维数数组组中中非非0元元素素个个数数例例7.17形形参参数数组组第第一一维维大大小小形形同同虚虚设设,无无论论如如何何定定义义,函函数数调调用用后后它它结结合合到到的的是是整整个个实实参参数数组组,故故可可以以不不指指定定形形参参数数组组第第一一维维的的大大小小。35intsolve(intb)intsum=0,i;for(i=0;i10;i+)if(bi!=0)sum+;return(sum);voidmain()inta10,num,i;for(i=0;i10;i+)scanf(%d,&ai);num=solve(a);printf(num=%dn,num);#include举举例例 编编写写函函数数统统计计一一维维数数组组中中非非0元元素素个个数数例例7.17 改改进进程程序序为为方方便便被被调调函函数数的的编编程程,通通常常另另设设一一参参数数用用于于传传递递数数组组元元素素的的个个数数。intb,intn)n,10);思思考考:将将实实参参数数组组定定义义为为a20行行吗吗?36举举例例 编编写写函函数数实实现现数数组组逆逆置置(1)voidfun(intx,intn)intt,i,j;for(i=0,j=n-1;ij;i+,j-)t=xi;xi=xj;xj=t;#includevoidmain()inti,a10=3,7,9,11,0,6,7,5,4,2;printf(Theoriginalarray:n);for(i=0;i10;i+)printf(%3d,ai);printf(n);fun(a,10);printf(Thearrayhasbeeninverted:n);for(i=0;i10;i+)printf(%3d,ai);/* /* 输输出出原原始始数数组组a */a */* /* 调调用用函函数数fun( ) fun( ) 逆逆置置数数组组a */a */* /* 输输出出逆逆置置后后的的数数组组a */a */类类例例7.19 7.19 :形形参参和和实实参参均均为为数数组组名名37voidfun(int*x,intn)intt,*i,*j,m=(n-1)/2;for(i=x,j=x+n-1;i=x+m;i+,j-)t=*i;*i=*j;*j=t;#includevoidmain()inti,a10=3,7,9,11,0,6,7,5,4,2;printf(Theoriginalarray:n);for(i=0;i10;i+)printf(%3d,ai);printf(n);fun(a,10);printf(Thearrayhasbeeninverted:n);for(i=0;i10;i+)printf(%3d,ai);/* /* 调调用用函函数数fun( )fun( )逆逆置置数数组组a */a */举举例例 编编写写函函数数实实现现数数组组逆逆置置(2) 形形参参为为指指针针变变量量,实实参参为为数数组组名名38voidfun(intx,intn)intt,i,j,m=(n-1)/2;for(i=0;i=m;i+)j=n-i-1;t=xi;xi=xj;xj=t;#includevoidmain()inti,a10=3,7,9,11,0,6,7,5,4,2,*p;printf(Theoriginalarray:n);for(i=0;i10;i+)printf(%3d,ai);printf(n);p=a;fun(p,10);printf(Thearrayhasbeeninverted:n);for(i=0;i10;i+)printf(%3d,ai);/*调调用用函函数数fun()逆逆置置数数组组*/形形参参为为数数组组名名,实实参参为为指指针针变变量量举举例例 编编写写函函数数实实现现数数组组逆逆置置(3)39#includevoidmain()inti,a10=3,7,9,11,0,6,7,5,4,2,*p;printf(Theoriginalarray:n);for(i=0;i10;i+)printf(%3d,ai);printf(n);p=a;fun(p,10);printf(Thearrayhasbeeninverted:n);for(i=0;i10;i+)printf(%3d,ai);/* /* 调调用用函函数数fun( )fun( )逆逆置置数数组组* */ / 形形参参、实实参参均均为为指指针针变变量量举举例例 编编写写函函数数实实现现数数组组逆逆置置(4)voidfun(int*x,intn)intt,*i,*j,m=(n-1)/2;for(i=x,j=x+n-1;i=x+m;i+,j-)t=*i;*i=*j;*j=t;40voidmain()inta10,inti;voidselect(int*a,intn)inti,j,k,temp;for(i=0;in-1;i+)k=i;for(j=i+1;jn;j+)if(ajak)k=j;if(k!=i)temp=ak;ak=ai;ai=temp;举举例例 编编写写函函数数用用选选择择法法实实现现从从小小到到大大排排序序printf(Enterthearray:n);for(i=0;i10;i+)scanf(%d,&ai);select(a,10);printf(thesortedarray:n);for(i=0;i10;i+)printf(%d,ai);printf(n);例例7.20#include41三三、多多维维数数组组名名作作函函数数参参数数 P223形形参参二二维维数数组组名名行行指指针针变变量量实实参参二二维维数数组组名名行行指指针针元元素素指指针针变变量量元元素素指指针针效效果果:函函数数调调用用期期间间,形形参参二二维维数数组组就就是是实实参参二二维维数数组组。等等同同等等效效42举举例例 编编写写求求二二维维数数组组最最大大值值intmax_value(inta4)inti,j,max;max=a00;for(i=0;i3;i+)for(j=0;jmax)max=aij;return(max);voidmain()inta34=1,3,5,7,2,4,6,8,15,17,34,12;printf(max=%dn,max_value(a);例例7.23形形参参二二维维数数组组的的第第一一维维大大小小可可以以不不指指定定,但但第第二二维维大大小小必必须须指指定定#include或或:intmax_value(int(*a)4)可可以以加加一一个个形形参参n,用用来来传传递递第第一一维维的的大大小小43四四、字字符符数数组组作作函函数数参参数数 P225形形参参一一维维字字符符数数组组名名字字符符指指针针变变量量实实参参一一维维字字符符数数组组名名字字符符指指针针效效果果:函函数数调调用用期期间间,形形参参字字符符串串就就是是实实参参字字符符串串。等等同同等等效效44举举例例 编编写写函函数数将将串串t复复制制到到串串svoidstringcopy(chars,char*t)inti=0;while(*t!=0)si=*t;i+;t+;si=0;#includevoidmain()charstr1=IloveBeijing!;char*str2=IloveChina!;stringcopy(str1,str2);printf(str1=%snstr2=%sn,str1,str2);调调用用函函数数复复制制例例7.24例例7.25改改用用两两个个字字符符指指针针变变量量作作形形参参voidstringcopy(char*p,char*q)while(*p+=*q+)!=0);45举举例例 将将串串s1第第k个个字字符符开开始始的的后后续续字字符符组组成成子子串串s2例例7.28voidcopysubstring(char*s1,char*s2,intk)s1=s1+k-1;/*假假设设k小小于于等等于于串串长长*/while(*s1!=0)*s2+=*s1+;*s2=0;举举例例 从从串串s1第第k个个字字符符取取n个个字字符符组组成成子子串串s2(若若不不足足n个个,取取所所有有后后续续字字符符)voidcopysubstring(char*s1,char*s2,intk,intn)s1=s1+k-1;while(n0&*s1!=0)*s2+=*s1+;n-;*s2=0;46main()函函数数.调调用用函函数数fun1fun1()函函数数.调调用用函函数数fun2fun2()函函数数结结束束7.4 函函数数的的嵌嵌套套调调用用和和递递归归调调用用从从什什么么地地方方调调用用函函数数,就就返返回回到到什什么么地地方方。7.4.1 函函数数的的嵌嵌套套调调用用47函函数数的的嵌嵌套套调调用用举举例例求求组组合合数数cnmfloatfac(intt)inti;floats=1;for(i=1;i=t;i+)s*=i;return(s);floatc(intm,intn)floatf,fac(int);f=fac(m)/(fac(n)*fac(m-n);return(f);返返回回c函函数数在在c函函数数中中三三次次调调用用fac函函数数返返回回main函函数数函函数数fac:求求t!函函数数C:求求cnm#includevoidmain()intm,n,t;floatc(int,int);scanf(%d%d,&m,&n);if(nm)printf(InputError!);elseprintf(%.0fn,c(m,n);在在main函函数数中中调调用用c函函数数48 int a(int n) int d,c,b(); d=a(c); 7.4.2 函函数数的的递递归归调调用用函函数数的的递递归归调调用用:在在定定义义一一个个函函数数的的过过程程中中又又直直接接或或间间接接地地调调用用函函数数本本身身递递归归函函数数两两要要素素 递递归归调调用用 使使递递归归结结束束的的条条件件49递递归归函函数数应应用用举举例例1年年龄龄问问题题intage(intn)intc;if(n=1)c=10;elsec=age(n-1)+2;return(c);#includevoidmain()printf(%dn,age(5);结结束束递递归归的的条条件件递递归归调调用用函函数数age:求求第第n个个人人的的年年龄龄P233例例7.32age(n-1)+2(n1)10(n=1)分分析析:age(n)=或或intage(intn)if(n=1)return10;elsereturnage(n-1)+2;50age(5)c=age(4)+2c=age(3)+2c=age(2)+2c=age(1)+2c=10(age(1)c=12(age(2)c=14(age(3)c=16(age(4)c=18(age(5)main()递递归归函函数数应应用用举举例例1年年龄龄问问题题51递递归归函函数数应应用用举举例例2 求求阶阶乘乘floatfac(intn)/*求求阶阶乘乘函函数数*/floatf;if(n=0|n=1)f=1;elsef=n*fac(n-1);return(f);#includevoidmain()intn;scanf(%d,&n);if(n0)printf(n1)分分析析:fac(n)=52递递归归优优点点:程程序序简简洁洁;有有时时能能解解决决非非递递归归方方法法不不能能解解决决的的问问题题。递递归归最最大大缺缺点点:效效率率低低原原因因如如下下:(1) 递递归归函函数数会会带带来来大大量量的的重重复复计计算算,例例如如n!程程序序,每每一一次次递递归归函函数数调调用用都都会会带带来来前前面面的的重重复复计计算算,大大大大降降低低效效率率(2) 函函数数的的每每一一次次调调用用都都需需进进行行保保留留现现场场、传传递递参参数数以以及及恢恢复复现现场场等等操操作作,效效率率低低递递归归函函数数的的优优缺缺点点537.5 函函数数的的返返回回值值为为指指针针l一一个个函函数数可可以以返返回回整整型型、字字符符型型、实实型型函函数数值值,也也可可以以返返回回一一个个指指针针值值,即即将将地地址址作作为为函函数数值值返返回回到到主主调调函函数数中中。这这样样的的函函数数叫叫做做返返回回指指针针的的函函数数,简简称称指指针针函函数数。54返返回回指指针针的的函函数数的的定定义义l指指针针函函数数的的定定义义: : 类类型型名名 * *函函数数名名(形形参参表表) 如如: : intint * *f(intf(int m,intm,int n) n) 表表示示f f是是一一个个函函数数, ,有有两两个个形形参参m m和和n,n,均均为为整整型型, ,函函数数的的返返回回值值是是一一个个指指向向整整型型数数据据的的指指针针注注意意:返返回回的的指指针针必必须须是是参参数数的的地地址址或或静静态态变变量量的的地地址址,不不能能是是函函数数体体内内定定义义的的动动态态变变量量的的地地址址。55举举例例 返返回回新新串串#includevoidmain()char*delspace(char*);chars100;gets(s);printf(%sn,delspace(s);char*delspace(char*s)int*p1,*p2;/*p1:原原串串指指针针,p2:新新串串指指针针*/p1=p2=s;while(*p1!=0)if(*p1=)p1+;else*p2+=*p1+;*p2=0;return(s);函函数数功功能能:从从串串s中中删删去去所所有有的的空空格格,返返回回删删去去空空格格后后的的s串串。567.6 变变量量的的作作用用域域和和存存储储类类别别变变量量按按照照其其作作用用范范围围分分为为:局局部部变变量量和和全全局局变变量量(外外部部变变量量)57局局部部变变量量和和全全局局变变量量inta=3,b=5;intmax(inta,intb)intc;c=ab?a:b;return(c);#includevoidmain()inta=8;printf(%dn,max(a,b);max()的的局局部部变变量量cmax()的的局局部部变变量量a、bmain()的的局局部部变变量量a实实参参a是是main()的的局局部部变变量量(8),实实参参b是是全全局局变变量量(5)使使用用max()的的局局部部变变量量a、b两两点点说说明明:不不同同函函数数中中的的局局部部变变量量可可以以同同名名,全全局局变变量量与与局局部部变变量量也也可可以以同同名名,但但它它们们代代表表不不同同的的变变量量,在在内内存存中中占占有有不不同同的的存存储储空空间间。局局部部变变量量起起作作用用时时,同同名名全全局局变变量量不不起起作作用用。全全局局变变量量a、b程程序序运运行行结结果果:858全全局局变变量量应应用用举举例例#includefloatMax,Min;floataverage(floatarray,intn)inti;floataver,sum=array0;Max=Min=array0;for(i=1;iMax)Max=arrayi;elseif(arrayiMin)Min=arrayi;sum=sum+arrayi;aver=sum/n;return(aver);voidmain()floatave;floatscore10,i;for(i=0;i10;i+)scanf(%f,&scorei);ave=average(score,10);printf(max=%6.2fnmin=%6.2fn,Max,Min);printf(average=%6.2fn,ave);有有一一个个一一维维数数组组,内内放放10个个学学生生的的成成绩绩,写写一一个个函函数数,求求出出平平均均分分、最最高高分分和和最最低低分分。P243例例7.40定定义义全全局局变变量量在在所所有有函函数数中中都都能能使使用用59函函数数间间数数据据传传递递的的渠渠道道:l主主调调函函数数(函函数数返返回回值值)被被调调函函数数l主主调调函函数数(普普通通变变量量参参数数)被被调调函函数数l主主调调函函数数(数数组组名名参参数数/指指针针变变量量参参数数)被被调调函函数数l主主调调函函数数(全全局局变变量量)被被调调函函数数函函数数间间数数据据传传递递的的渠渠道道不不提提倡倡使使用用!60变变量量的的存存储储类类别别l变变量量按按其其生生存存的的时时间间(生生存存期期)划划分分为为动动态态存存储储变变量量和和静静态态存存储储变变量量。l变变量量定定义义完完整整格格式式: 存存储储类类别别 数数据据类类型型 变变量量表表列列;存存储储类类别别缺缺省省为为autoauto(自自动动型型)61(一一)内内存存中中用用户户区区存存储储空空间间的的分分配配内内存存系系统统区区用用户户区区存存放放系系统统程程序序存存放放用用户户文文件件和和数数据据程程序序区区:静静态态存存储储区区:动动态态存存储储区区:程程序序全全局局变变量量静静态态局局部部变变量量自自动动局局部部变变量量62(二二)变变量量的的存存储储类类别别63局局部部静静态态变变量量应应用用举举例例1#includeintmyfun()autointx=1;staticinty=1;x=x+2;y=y+2;return(x+y);voidmain()inti=0,a=0;for(i=1;i=2;i+)a=myfun();printf(%4d,a);程程序序运运行行结结果果:6 8动动态态变变量量x,每每次次调调用用时时都都赋赋初初值值1 静静态态变变量量y,只只在在编编译译时时赋赋初初值值1,每每次次调调用用结结束束后后保保留留其其值值 例例7.3864局局部部静静态态变变量量应应用用举举例例2#includeintfac(intn)staticintf=1;f=f*n;return(f);voidmain()inti;for(i=1;i=5;i+)printf(%5dn,fac(i);程程序序运运行行结结果果: 1 2 6 24 120利利用用静静态态局局部部变变量量求求阶阶乘乘65变变量量的的分分类类按按数数据据类类型型字字符符型型变变量量数数值值型型变变量量整整型型变变量量实实型型变变量量长长整整型型变变量量基基本本整整型型变变量量无无符符号号整整型型变变量量单单精精度度型型变变量量双双精精度度型型变变量量按按作作用用域域全全局局变变量量(外外部部变变量量)局局部部变变量量(内内部部变变量量)按按生生存存期期动动态态存存储储变变量量静静态态存存储储变变量量667.7 内内部部函函数数和和外外部部函函数数内内部部函函数数:只只能能被被本本文文件件中中函函数数调调用用的的函函数数外外部部函函数数:允允许许被被其其它它文文件件调调用用的的函函数数一一、用用static定定义义内内部部函函数数staticintf()二二、用用extern定定义义外外部部函函数数(通通常常省省略略extern)externintg()三三、用用extern声声明明其其它它文文件件中中定定义义的的外外部部函函数数(通通常常省省略略extern)例例externintg();自自学学
网站客服QQ:2055934822
金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号