资源描述
单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,*,第 8 章 函数,8.1,概述,8.2,函数定义的一般形式,8.3,函数参数和函数的值,8.4,函数的调用,8.5,函数的嵌套调用,8.6,函数的递归调用,8.7,数组作为函数参数,8.9,变量的存储类别,8.10,内部函数和外部函数,8.8,局部变量和全局变量,1,在进行程序设计时,程序员总是将复杂的问题进行,分解,化整为零。编写一段小程序就能解决一个小问题,,然后将这些小程序拼装起来就能解决非常大而复杂的问,题。在 C 中,这些小程序统称为函数。,在 C 中,由系统提供的函数放在函数库中供用户选,用,以减少重复编写程序模块的工作量。,所有函数都是平行的,相互独立不能嵌套,但可以相,互调用。,C 函数分标准函数(库函数)和自定义函数。,C 函数本身分有参函数和无参函数。,8.1 概述,第 8 章 函数,2,8.2 函数定义的一般形式,1无参函数的定义形式,类型标识符 函数名(),说明部分;,语句;,无参函数一般不需要返回函数值,可以省略类型标识符。,2有参函数的定义形式,类型标识符 函数名(形式参数表),形式参数说明;,说明部分;,语句;,3,例:int max(x,y),int x,y;,/,形式参数说明,/,int z;,/,函数体中的说明部分,/,z=xy?x:y;,return(z);,类型说明符 函数名(),“空函数”什么操作也不做。其作用是在此处留一函数的,位置,以便将来扩充功能之用。函数名也在将来换取实,际的函数名。,这两行可以写成一行:,int max(int x,int y),3“空函数”,4,8.3 函数参数和函数的值,1形式参数和实际参数,例8.2 从键盘输入两个数,输出其中较大的一个。,main(),int a,b,c;,scanf(“%d,%d”,c=max(a,b);,/,a,b为实际参数,/,printf(“Max is%d”,c);,max(x,y),/,x,y为形式参数,/,int x,y;,int z;,z=xy?x:y;,return(z);,5,注意,:,形参变量在被调用前不占用存储单元;在被调用结束,后,形参所占存储单元亦被释放。,实参可以是常量、变量或表达式。,必须指定形参类型,且必须与实参的类型一致。,实参对形参的数据传递是“值传递”。即单向传递,不,能逆传。,可以在形参表中直接说明形参类型。,如:,int max(int x,int y);,float fun(int a10,int n);,6,2函数的返回值,函数的返回值是通过return语句获得的。当不需返,回函数值时,可省去return语句。,return语句的后面可以有括号,也可以没有。,如:,return z,;,return(z);,return语句的后面可以是变量,也可以是表达式。,如:,return(x y?x:y);,return语句返回值的类型应与该函数的类型一致。,否则以函数类型为准。,7,若函数中没有return语句,则该函数被调用后也会带,回,不确定的值,。,int a,b,c;,a=printstar();,b=print_message();,c=printstar();,printf(“%d,%d,%dn”,a,b,c);,输出的a,b,c的值将是各个被处理的字符串的长度。,为了明确表示不需要函数返回值,可以用“,void,”定义,函数为“,无类型,”。此时,不得使用,a=printstar(),之,类的语句。,凡不需要返回值的函数,一般均定义为“,void,”类型。,如:,均为处理字符串的函数,且均没有,return,语句。,8,8.4 函数的调用,1函数调用的一般形式,函数名(实参表),说明:,对于无参函数,尽管没有“实参表”,但也不得省略,括号。,“实参表”中的参数之间用,逗号,分开。,实参与形参之间的个数及类型必须一一对应。,对实参求值的顺序是自左至右还是自右至左,视具体,的系统而定。Turbo C 和 MS C 是按,自右至左,的顺,序求值。,9,例8.4,main(),int i=2,p;,p=f,(i,+,+,i);,printf(“%d”,p);,int f,(,a,b);,int a,b;,int c;,if (a b)c=1;,else if(a=,=b)c=0;,else c=1;,return(c);,输出结果:,0,注意:,这里是按,自右至左,求,值的,相当于,fun(3,3),。若,按,自左至右,求值,则相当于,fun(2,3),则输出为,1。,先执行+i 使 i 的值为,3,再将 i 的值 3 传递给 b,b,的值为,3,然后将 i 的值 3 传递给,a,a,的值为,3,10,2函数调用的方式,调用函数,可以有如下三种方式:,将函数调用作为一个语句。,如:,printf(“MS C programming”);,gets(s);,将被调用的函数写在表达式中。,如:,c=2,max(a,b);,注意,:被调用函数 max 必须有确定的返回值。,将函数调用作为一个函数的实参。,如:,m=max(max(a,b),c);,3对被调用函数的说明,在一个函数中调用另一个函数时:,如果被调函数为库函数,则应在文件开头用“,#include,”命令,声明相应的“头文件”。,如:,#include“stdio.h”,#include“math.h”,11,如果被调函数为自定义函数且其定义在主调函数定义之后,则,应在主调函数中说明其类型。,类型标识符 被调函数名();,如:float add();,其语句形式为:,如果被调函数为自定义函数且其定义在主调函数定义之前,则,在主调函数中可不必说明其类型。因为编译程序已知道其类型,如果被调函数的值是整型或字符型,可不必说明类型,系统自,动按整型说明。,如果在所有被调函数定义之前、在文件的开头、在函数的外部,已对被调函数作了类型说明,则在各主调函数中可不必说明其,类型。,如:,char letter();,float f();,int i();,main(),/,主调函数中不必说明它所调用的函数的类型,/,一开始就将所有要被,调用的函数作出声明,12,例:编程求11999之间的数 m,而 m、m,2,和 m,3,均是回文数。,如:m=11、m,2,=121、m,3,=1331,。,#include“stdio.h”,main(),long int m;,for(m=11;m1000;m+),if(,fun(m),&,fun(m,m),&,fun(m,m,m),),printf(m=%ld,t m,m=%ld,t m,m,m=%ldn,m,m,m,m,m,m);,int fun(long n),long i,m;,i=n;m=0;,while,(i)m=,m,10+i%10,;,i/=10,;,if(m=n)return 1;,else return 0;,局部变量 i 存放 n 的值即主,调函数中 m 传递过来的值,这里的 m 是局部变量,不要,与主函数中的 m 混淆。,13,8.5 函数的嵌套调用,C 语言函数的定义都是相互平行、独立的,不能嵌套定义。但可以嵌套调用函数。所谓函数的嵌套调用就是在被调用的函数中又调用另外的函数。,Main(),x=root(x1,x2);,/*调用root函数*/,Float root(float y1,float y2),y1=f(x);,/*调用f 函数*/,14,8.6 函数的递归调用,自己调用自己,递归一次,分配一次存储,单元,返回时,一层一层返回;,2 递归程序示例,1 递归的概念,递归分为:,直接递归:函数中自己调用自己;,间接递归:在调用其他函数中调用自己。,15,例8.7 有5人排成一队,从最后一人开始,其年龄均比,前面的人大2岁,而最前面的人年龄是10岁,问,最后一人的年龄是多少岁?,main(),age(5),age(4)+2,age(n),n=5,age(3)+2,age(n),n=4,age(2)+2,age(n),n=3,age(1)+2,age(n),n=2,age(1),age(n),n=1,age(1)=10,age(2)=12,age(3)=14,age(4)=16,age(5)=18,输出,age(5),age(n),int n;,int c;,if(n=1)c,=,10;,else c,=,age(n,1)+2;,return(c);,main(),printf(“%dn”,age(5);,运行结果,:,18,16,函数的递归调用利用了堆栈技术。在本例中:,Age(5),Age(5,1,)+2,Age(4,1,)+2,Age(3,1,)+2,Age(2,1,)+2,10+2=12,12+2=14,14+2=16,16+2=18,18,Age(2,1,)+2,Age(3,1,)+2,Age(4,1,)+2,Age(5,1,)+2,Age(5),Age(5),Age(5,1,)+2,Age(4,1,)+2,Age(3,1,)+2,Age(2,1,)+2,入栈,出栈,出栈结果,17,例:把一非零的整数倒序打印,main(),int aa();,int n;,scanf(“%d”,aa(n);,int aa(x),int x;,printf(“%d”,x%10);,if(x/10!=0),aa(x/10);,18,例:读入一串字符,并倒序打印,main(),char abc();,abc();,char abc(),char ch;,scanf(“%c”,if(ch!=.),abc();,printf(“%c”,ch);,19,例:求两个数的最大公约数,main(),int gcd(a,b);,int n,m;,scanf(“%d%d”,printf(“GCD=%d”,gcd(m,n);,int gcd(int a,int b),int c,g;,c=a%b;,if(c=0)g=b;,else g=gcd(,b,c,);,return(g);,20,8.7 数组作为函数参数,1,数组元素作函数实参,用法与变量参数相同,是单向传递,即“值传递”方式。,例:,main(),y=fun(a0,a1.a2);,float fun(float,a,float,b,float,c,),float sum,aver;,sum=a+b+c;,aver=sum/3.0;,return(aver);,21,8.7 数组作为函数参数,2,数组名作函数实参,此时,实参数组名和形参数组名都应,分别在各自所在的函数中定义;采取“地址,传送”方式,即:把实参数组的起始地址传,给形参数组,这样,实参数组和形参数组共,占同一段内存单元。,22,例:,main(),float fun1(float x3);,float a3=80.0,90.0,100.0;,float ave;,ave=fun1(,a,);,printf(“%fn”,ave);,float fun1(float,x3),float sum,aver;,sum=x0+x1+x2;,aver=sum/3.0;,return(aver);,Float fun1();,Float fun1(x),float x;,或,float x3;,23,例:用函数调用实现字符串的复制。,void copy_string(from,to),char from,to;,int i=0;,while(from,i,!=0),to,i,=from,i,;i,+,+;,to,i,=0;,main(),char a =“I am a teacher.”;,char b =“you are a student.”;,copy_string(,a,b),;,printf(“string_a=%snstring_b=%sn”,a,b);,声明形参,from,to,为字符数组
展开阅读全文