资源描述
单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,8.1,概述,8.2 函数定义普通形式,8.3 函数参数和函数值,8.4,函数调用,8.5 数组作为函数参数,8.6 局部变量和全局变量,8.7,变量存放类别,8.8 内部函数和外部函数,8.9 怎样运行一个多文件程序,第八章 函数,第1页,8.1 概述,(1)一个源程序文件是由一个或多个函数组成。一个源程序文件是一个编译单位。,(2)一个C程序文件由一个或多个源程序文件组成。,(3)C程序执行从main函数开始,调用其它函数后回到main函数,并在main函数中结束整个程序运行。,(4)全部函数都是平行,在定义函数时是相互独立,,函数不能嵌套定义;函数间能够相互调用,但不能调用main函数。,(5)从用户使用角度看,函数分为,标准函数和用户自定义函数,两种。,(6)从函数形式看,函数分为,无参函数和有参函数,两种。,如:,第2页,#include,printstar(),printf(*n);,print_message(),printf(How do you do!n);,main(),printstar();,print_message();,printstar();,第3页,8.2 函数定义普通形式,1.无参函数定义,类型标识符 函数名(),申明部分,语句,2.有参函数定义,类型标识符 函数名(形式参数列表),申明部分,语句,3.“空函数”定义,类型标识符 函数名(),注意:假如在定义函数时不指定函数参数,系统会隐含指定函数类型为,int型,。,第4页,#include,int max(int x,int y)/或采取传统方式 int max(x,y),/int x,y;,int z;/int z;.,z=(xy)?x:y;,return z;,main(),int c,a,b;,scanf(%d,%d,c=max(a,b);,printf(%d,c);,return 1;,第5页,8.3 函数参数和函数值,1.形式参数和实际参数,实际参数:主调函数中提供数据。能够是常量、变量、表示式等,是详细数值。,形式参数:被调函数中用以接收主调函数数据变量,。,(1)在定义函数中指定形参,在未出现函数调用时,不占内存中存放单元。在调用结束后,形参所占内存单元也被释放。,(2)实参能够是常数、变量或表示式,但要求有确定值。调用时将实参值赋给形参(形参是数组名除外)。,(3)在被定义函数中,必须指定形参类型。,(4)实参加形参类型应相同或赋值兼容。若类型不一样,则进行类型转换,将实参类型转换为形参类型。,(5)实参变量对形参变量数据传递是单向值传递。,2,a,2,x,3,b,3,y,2,a,10,x,3,b,15,y,第6页,2.函数返回值,(1)函数返回值是经过函数中return语句取得。,return(表示式);或 return 表示式;,(2)函数值类型是在函数定义时指定。C语言要求,凡不加类型说明函数,,一律按整型处理。,(3)假如函数值类型与return语句中表示式值类型不一致,则,以函数类型为准,并自动进行类型转换,。(如:见例子),(4)假如被调用函数中没有return语句,函数带回是一个不确定值。,(5)为了明确表示“不带回值”,能够用“void”定义“无类型。,第7页,#include,int max(float x,float y),return(xy)?x:y);,main(),int c;,float a,b;,scanf(%f,%f,c=max(a,b);,printf(%d,c);,return 1;,第8页,8.3 函数调用,主调函数:主动去调用其它函数,被调函数:被其它函数所调用,1.函数调用普通形式,函数名(实参列表);,含多个实参,则各参数用逗号分开,实参加形参个数应相等(不等则犯错),类型应一致(不一致则转换),实参求值次序是不确定,有从左至右,有从右至左(如TC,MS C)。,按函数在程序中出现位置不一样,函数调用可分为:,函数语句:printstar();,带返回值函数语句:p=f(i,i+);/,注意求解次序问题,函数表示式:c=2*max(a,b);,函数参数:m=max(a,max(b,c);,第9页,2.对被调函数申明和函数原型,在一个函数中调用另一个函数需要具备:,(1)被调函数必须是已经,存在,函数(库函数或自定义函数)。,(2)假如被调函数是库函数,普通应该在文件开头用#include命令将相关头文件包含到本文件中来(见附录V)。如:,#include,(3)假如被调函数是自定义函数,且与主调函数在同一个文件中,普通应该在主调函数中在调用之前对被调函数作申明。格式:,函数类型 函数名(参数类型1,参数类型2,);,函数类型 函数名(参数类型1 参数名1,参数类型2 参数名2,);,(4),函数调用时函数名、实参个数应与函数定义一致,实参类型必须与函数定义中形参类型赋值兼容。,第10页,#include,main(),float add(float x,float y);,float a,b,c;,scanf(%f,%f,c=add(a,b);,printf(sum is%f,c);,return 1;,float add(float x,float y),float z;,z=x+y;,return(z);,第11页,函数申明语句中。,(1),函数类型 函数名(参数类型1,参数类型2,),(2),函数类型 函数名(参数类型1 参数名1,参数类型2 参数名2,),称为函数原型:编译系统不检验参数名,所以参数名是什么都无所谓。,但应确保函数原型与函数首部写法一致,即函数类型、函数名、参数个数、参数类型和参数次序必须相同。,说明:,以前C版本只申明函数名和函数类型,不包含参数类型和参数个数。,假如函数调用之前,没有对函数作申明,则编译系统会把第一次碰到该函数形式作为函数申明,并将函数类型默认为int型,即假如函数类型为整型或字符型,能够在函数调用之前无须作函数申明(但不对参数类型和个数进行检验)。,假如函数定义在主调函数之前,则能够无须申明。,也能够在全部函数之前,在函数外部进行函数申明。如:,第12页,char letter(char,char);,float f(float,float);,int I(float,float);,main(),char letter(char c1,char c2);,float f(float x,float y);,int I(float j,float k);,第13页,8.4 函数嵌套调用,C语言,不允许嵌套定义函数,但能够嵌套调用函数,,即,在调用一个函数过程中,又调用另一个函数。,函数嵌套调用图示,main,a函数,b函数,调用a函数,调用b函数,1,2,3,4,5,6,7,8,9,结束,第14页,8.5 函数递归调用,递归:在函数调用过程中,直接或间接调用本身。,1.直接递归:在函数体内又调用本身,如:int f(int x),int y,z;,z=f(y);,return(2*z);,2.间接递归:当函数去调用另一函数时,而另一函数反过来又调用本身。,f1(),调用f1(),f1()函数 f2()函数,调用f2()函数 调用f1()函数,第15页,能够看到,这两种递归调用都是无终止本身调用,处理无终止递归调用方法是:,确定好结束递归条件,。,条件成立,进行递归,用if语句控制,条件不成立:结束递归,第16页,例 有5个人在一起问年纪,第5个人比第4个人大2岁,第4个人比第3个人大2岁.第2个人比第1个人大2岁,第1个人为10岁。,age(5)age(4)age(3)age(2)age(1),=2+age(4)=2+age(3)=2+age(2)=2+age(1)=10,=18 =16 =14 =12,10 n=1,用式子表示:age(n)=,age(n-1)+2 n1,第17页,问年纪递归程序以下:,age(int n),int c;,if(n=1)c=10;,else c=2+age(n-1);,return(c);,main(),printf(“%dn”,age(5);,第18页,用递归法求n!,float fac(int n),float f;,if(n 0),printf(“n1),第19页,8.6 数组作为函数参数,1、数组元素做函数参数,数组元素作实参时,与变量作实参一样,也是,单向传送,。,2、数组作为函数参数,数组名作实参时,,实参和形参都用数组名,传送是数组地址(地址常量),。调用函数时,对形参数组元素操作,实际上也是对实参数组元素操作,。,几点说明:,数组名作形、实参数时,应分别在主、被调函数中对其申明为数组;,形、实参数数组类型要,完全一致,(,int,char,也不能通用);,形参数组能够不,指定大小,,需要时能够用一,实参将数组长度传递给形参,;,数组名作参数时,传递是,地址值,,对形参数组操作实际上也是对实参数组操作。,第20页,3、多维数组名作为函数参数,多维数组名作实参和形参时,,形参数组能够指定每一维大小,也能够省略第一维大小,,二者等价。,8.7局部变量和全局变量,1、局部变量,局部变量:作用域仅限在所定义函数或复合语句内部,。,说明:,(1)在不一样函数(包含,main,函数)中允许同名,它们占据不一样内存单元,相互之间互不影响。,(2)形参属局部变量,只能在其所在函数内部使用。,(3)能够在复合语句中定义变量,这些变量只在本复合语句中有效且能够与整个函数变量同名。,第21页,2、全局变量,全局变量:在一个文件全部函数以外定义变量称为外部或全局变量。,作用域:从定义变量位置开始到源程序结束。,说明:,在源程序开始定义全局变量,对源程序中全部函数有效,在源程序中间定义全局变量,仅对其后面全部函数有效,在函数或复合语句中定义局部变量假如与全局变量同名,则局部变量优先,全局变量不起作用.,全局变量使用,增加了函数间数据联络渠道,同一文件中全部函数都能引用全局变量值,当某函数改变了全局变量值时,便会影响其它函数。,第22页,#include,int a=3,b=5;/*全局变量作用域及其使用情况*/,max(int a,int b),int c;,c=ab?a:b;,return(c);,void main(),int a=8;,printf(%d,max(a,b);,第23页,8.8 变量存放类别,1、动态存放方式与静态存放方式,在C中,每一个变量和函数有两个属性:数据类型和数据存放类别。依据变量存放类别,能够知道变量作用域和生存期。从变量值作用域可分为全局变量和局部变量,从变量值存在时间即生存期来看,又可分为:,(1)静态存放方式:即程序运行期间为其分配存放单元是固定。,(2)动态存放方式:程序运行期间依据需要为其动态分配存放单元。,程序运行时,在内存中存放情况以下:,第24页,代码段,数据段,程序区,静态存放区,动态存放区,编译、连接后生成指令代码。,外部、局部静态(static):,程序运行开始到结束一直占用,形参、自动变量、函数调用时,现场保护和返回值等。,函数调用时分配存放单元,,调用结束时释放,用户区,第25页,2、auto变量,函数内部无static申明局部变量、函数中形参均为自动变量。当变量存放类别为自动时,申明符auto可省;自动变量被分配在动态区,未赋初值时,其值未定义,每次调用重新赋值。,比如:,int f(int a),auto int b,c=3;,3、,用static 申明局部变量,若希望函数调用结束后,其值不消失,下次调用函数时继续使用,则用static对变量加以申明为“静态局部变量”。,如:,第26页,例 考查静态局部变量值,f(int a),auto int b=0;,static int c=3;,b=b+1;c=c+1;,return(a+b+c);,main(),int a=2,i;,for(i=0;i3;i+),printf(“%d ”,f(a);,main(),i a f(a),0 2 f(2),1 2 f(2),2 2 f(2),f(a),a b c return(a+b+c),2 0 3,1 4 return(7),2 0 4,1 5 return(8),2 0 5,1 6 return(9),运行结果:7 8 9,第27页,静态局部变量说明:,(1)分配在静态区,程序运行结束释放存放单元。,(2)仅开始时赋初值一次(未赋初值时为0),以后每次调用函数时,变量不再赋值,前次操作结果被保留。,(3)局部动态变量若未赋初值,其值是不确定,所分配存放单元是不固定;而局部静态变量未赋初值,其值为0(字符型变量值为0),所分配存放单元是固定。,(4)静态局部变量在函数调用结束后虽存在,但其它函数不能引用它。,第28页,使用局部静态变量有以下几个情况,(1)需要保留上一次调用结束时值,例 打印 15阶乘值,int fac(n),int n;,static int f=1;,f=f*n;return(f);,main(),int i;,for(i=1;i=5;i+),printf(“%d!=%dn”,i,fac(i);,(2)初始化后变量只被引用而不改变其值,则用静态局部变量较方便,缺点:从程序运行开始到结束一直占用内存,这么会浪费系统资源。,第29页,4、,register变量,CPU内部有存放器组可用来存放数据,若把数据申明为存放器类型,则将该类型数据存放在存放器中,其优点在于:,降低数据与内存之间交换频率,,提升程序效率和速度,。,int fac(int n),register int i,f=1;,for(i=1;i=n;i+),f=f*i;,return(f);,main(),int i;,for(i=1;iy?x:y;,return(z);,main(),extern A,B;/*类型名可写也可省略*/,printf(“%d”,max(A,B);,int A=13,B=-8;,第32页,(2)在多文件程序中申明外部变量,当一个程序由多个文件组成时,要在一个文件中引用另一文件中定义外部变量时,此时要用extern加以申明;,若在两个文件中都要使用同一个外部变量,若同时对同名外部变量申明,则系统将提醒“重定义类型错”,处理方法是:在任一文件中定义外部变量,在另一文件用,extern,对该变量作“外部变量申明”。,比如,,file1.c为:,int A,main(),文件,file2.c为:,extern A;,power(int n);,第33页,6、用static 申明外部变量,若使全局变量只限于定义它文件中函数引用,而不让其它文件中函数引用,需要用static加以说明,称为静态全局变量。,(注意:此种说法只在工程方法中有效,而在文件包含中则不起作用),第34页,7、关于变量申明和定义,申明部分:对相关标识符(变量,函数,结构体)属性进行说明。对于函数,申明和定义区分显著,申明是函数原型,定义是函数本身,是一个独立程序模块;,对于变量,有两种情况:,1.定义性申明:需建立存放空间,如int a;也称定义。,2.引用性申明:不建立存放空间,如extern A,广义地讲,申明包含定义,但并非全部申明都是定义;,如:int A;既包含申明又包含定义;,extern A;只是申明,而无定义。,约定:建立存放空间申明称定义;,不建立存放空间申明称申明。,auto,register,static申明变量时,是在定义变量基础上加上这些关键字,不能单独使用。,第35页,8、存放类别小结,在C中,定义数据需指出数据类型和存放类别。,(1)作用域:变量在某个文件或函数范围内是有效,则称该文件或函数是该变量作用域。,自动(动态局部)变量:离开函数,值消失,静态局部变量:离开函数,值仍保留,存放器变量:离开函数,值消失,形式参数:可定义为自动或存放器变量,局部变量,静态外部变量:只限本文件引用,外部(非静态)变量:允许其它文件引用,全局变量,第36页,(2)生存期:变量在某一时刻是存在,认为这一时刻属于该变量生存期:,自动变量(本函数内有效),存放器变量(本函数内有效),形式参数,动态存放,静态局部变量(函数内有效),静态外部变量(本文件内有效),外部变量(其它文件可引用),静态存放,第37页,(3)从变量存在位置来分,:,静态局部变量,静态外部变量(函数外部静态变量),外部变量(可为其它文件引用),内存中静态存放区,内存中动态存放区,自动变量和形式参数,CPU 中 存放器,存放器变量,第38页,8.9 内部函数和外部函数,函数能否被其它源文件中函数调用,看其是内部还是外部函数,1、内部函数,只能被本文件中其它函数所调用,形式:static 类型标识符 函数名(形参表列),若是内部函数,其作用域仅限于定义它所在文件。此时在其它文件中能够有相同函数名,它们相互之间互不干扰。,2、外部函数,能被其它文件中函数所调用,。,形式:extern 类型标识符 函数名(形参表列),注意:extern 可省,隐含时,系统默认其为外部函数。,第39页,8.10 怎样运行一个多文件程序,1.用turbo C集成环境,(1)工程方法,建立工程文件名.prj,其中包含一个程序各文件名,,在工程菜单项中设置工程文件名,运行工程文件,按F9,(2)文件包含方法,在主函数头部将本程序各文件用#include“文件名.c”,编译时,系统自动将“文件名.c”放到,main函数前头,作为一个整体编译。这时,这些函数被认为是在同一个文件中,函数中extern申明能够不要。,运行该程序,2.在,MS C上,分别对4个文件进行编译,得到4个.obj,文件,link file1+file2+file3+file4 得可执行文件,file1.exe,第40页,以下程序输出结果是:_,。,main(),int x=0;,sub(,printf(%dn,x);,sub(int *a,int n,int k),if(k=n)sub(a,n/2,2*k);,*a+=k;,第41页,#include int i=10;int main()int i=1;printf(%dt,i);int i=2;pritnf(%dt,i);extern i;i+=1;printf(%dt,i);printf(%dt,+i);,printf(%dn,+i);return 0;运行结果为 1 2 11 3 2,第42页,例、写出下面程序执行结果。,int k=3;main()int k=7;printf(k=%dn,k);int k=11;printf(k=%dn,k);k+=1;printf(k=%dn,k);printf(k=%dn,k);printf(k=%dn,k);,k=7,k=11,k=12,k=12,k=7,第43页,例、写出以下程序执行结果。,#include stdio.hint i=3;main()int i,j;i=f1();for(j=3;j6;+j)printf(i=%d,j=%dn,i,j);printf(f2(%d)=%dn,i,f2(i);printf(f3(%d)=%dn,i,f3(i);printf(f4(%d)=%dn,i+j,f4(i+j);getch();,int f1()return i;,int f2(int j)return j=+i;,int f3(int j)static int i=9;return j=i-;,int f4(int i)int j=10;return i=j+=i;,i=3,j=3f2(3)=4f3(3)=9f4(6)=16,i=3,j=4f2(3)=5f3(3)=8f4(7)=17,i=3,j=5f2(3)=6f3(3)=7f4(8)=18,第44页,以下程序运行后,输出结果是,_,func(int a,int b),static int m=0,i=2;,i+=m+1;,m=i+a+b;,return(m);,main(),int k=4,m=1,p;,p=func(k,m);printf(“%d,”,p);,p=func(k,m);printf(“%dn”,p);,第45页,编写函数fun,该函数功效是:从字符中删除指定字符,同一字母,大、小写按不一样字符处理。,void fun(char s,int c),int i=0;,char*p;,p=s;,while(*p),if(*p!=c),si=*p;i+;,p+;,si=0;,第46页,请编写一个函数fun,它功效是:输出一个字符串长度。,(不得调用C语言提供求字符串长度函数)。,int fun(char*s),int i=0;,while(*s+)i+;,return i;,第47页,请编写函数fun,其功效是:将s所指字符串中除了下标为偶数、,同时ASCII值也为偶数字符外,其余全都删除;串中剩下,字符所形成一个新串放在t所指一个数组中。,void fun(char*s,char t),int i,j,n;,n=strlen(s);,for(i=0;in;i+),if(i%2=0&si%2=0),tj=sj;,j+;,tj=0;,第48页,请编写一个函数fun,它功效是:将ss所指字符串中全部下标,为奇数位置上字母转换为大写(若该位置上不是字母则不转换)。,void fun(char*ss),int i,n;,n=strlen(ss);,for(i=1;i=a&ssi=z),ssi=ssi-32;,第49页,一个整数,它加上,100,后是一个完全平方数,再加上,168,又是,一个完全平方数,请问该数是多少?,#include math.hmain()long int i,x,y,z;for(i=1;i100000;i+),x=sqrt(i+100);,/*x,为加上,100,后开方后结果*,/,y=sqrt(i+268);,/*y,为再加上,168,后开方后结果*,/,if(x*x=i+100&y*y=i+268),/*,假如一个数平方根平方等于该数,,这说明此数是完全平方数*,/,printf(n%ldn,i);,第50页,一个数假如恰好等于它因子之和,这个数就称为“完数”。,比如,6=1,2,3.,编程找出,1000,以内全部完数。,main()static int k10;int i,j,n,s;for(j=2;j1000;j+),n=-1;,s=j;,for(i=1;iJ;I+),if(j%i)=0),n+;,s=s-i;,kn=i;,if(s=0),printf(%d is a wanshu,j);,for(i=0;iN;I+),printf(%d,ki);,printf(%dn,kn);,第51页,以下函数调用语句中含有_个参数。,func(f1,f2),(f2,f3,f4),f5),A)3 B)4 C)5 D)6,以下程序运行结果是_。,main(),char arr24;,strcpy(arr,“you”);,strcpy(arr1,“me”);,printf(“%sn”,arr);,A)you me B)you C)me D)arr,第52页,以下程序输出结果是_。,int f(),static int i=0;,int s=1;,s+=i;i+;,return s;,main(),int i,a=0;,for(i=0;i5;i+)a+=f();,printf(“%dn”,a);,A)20 B)24 C)25 D)15,第53页,程序中对fun函数有以下说明:,void*fun();,此说明含义是_。,A)fun函数无返回值,B)fun函数返回值能够是任意数据类型,C)fun函数返回值是无值型指针类型,D)指针fun指向一个函数,该函数无返回值,第54页,设有以下程序:,int fun(char*s),int n=0;,while(*s)n+;s+;,return n;,main(),char y=“this_is_an_example。”;,printf(“%dn”,fun(&y6);,该程序输出结果是_。,第55页,以下程序功效是_。,int fun(char*a),char*b=a;,while(*b)b+;,return b-a;,第56页,main()char b=Hello,you;b5=0;printf(%sn,b);,第57页,练习,1.,编写程序求出全部满足以下条件四位数:其前两位数字与其后两位数字之和平方等于该数本身。比如:3025=(30+25),2,练习2假定输入字符串中只包含字母和*号。请编写程序将字符串中全部*删除,删除后字符串仍存放在原来数组中。比如,字符串中内容为:“*ab*A*BC*DEF*G*”,则删除后字符串为:“abABCDEFG”。,练习3:输出100-200间全部素数,第58页,
展开阅读全文