收藏 分享(赏)

c语言(第八章函数).ppt

上传人:weiwoduzun 文档编号:5248161 上传时间:2019-02-14 格式:PPT 页数:81 大小:448.50KB
下载 相关 举报
c语言(第八章函数).ppt_第1页
第1页 / 共81页
c语言(第八章函数).ppt_第2页
第2页 / 共81页
c语言(第八章函数).ppt_第3页
第3页 / 共81页
c语言(第八章函数).ppt_第4页
第4页 / 共81页
c语言(第八章函数).ppt_第5页
第5页 / 共81页
点击查看更多>>
资源描述

1、第八章 函数,函数定义的一般形式 函数参数和函数的值 函数的调用 数组作为函数参数 函数的嵌套调用 函数的递归调用 局部变量和全局变量 内部函数和外部函数,8.1 概 述,main() star(); message(); star(); star() printf(“*n“); message() printf(“game over!n“); ,1、一个源文件由一个或多个函数组成。是一个编译单位。 2、一个C程序由一个或多个源文件组成。 3、C程序的执行由main函数开始,调用其他函数后回到main函数。 4、所有的函数都是平行的,在定义的时候相互独立。一个函数并不从属于另一个函数。 5、从

2、用户角度看,函数有两种:标准函数(库函数)、用户自定义函数。,函数的分类: 1、根据有无返回值分:2、根据函数有无参数来分:,8.2 函数定义的一般形式,1.无参函数定义一般形式类型标识符 函数名 ( )说明部分语句 例如:nihao( ) /*nihao函数,功能:显示一字符串*/ printf(“ How do you do!n“); ,该函数无形式参数列表,类型标识符指定函数值的类型,即函数带回来的值的类型。如果省略,系统隐含指定为int 型。,例如:int max ( int x, int y) int z; /*函数内部定义的变量*/ z = xy ? x:y; return (z)

3、; /*return语句使函数结束执行,返回主调函数,括号的的z值作为函数带回的值(返回值)。*/ ,2.有参函数定义一般形式类型标识符 函数名 (形式参数列表) 说明部分语句 ,类型标识符,函 数 名,形式参数列表,该函数有 两个形式参数,均为整型,3、函数定义的其他形式,1).可以有空函数int dummy ( ) 2).无返回值函数void doit (.). . 类型标识符说明为void,表示函数无返回值,即该函数执行后不返回任何值。,无形式参数,函数体中无任何语句,称为“空函数,8.3 函数参数和函数的值,一、形式参数和实际参数 形式参数:在定义函数时使用的参数, 简称“形参”。 形

4、参是一个变量. 实际参数:在调用函数时使用的参数,简称“实参”。 实参是一个表达式.主调用函数与被调用函数之间的数据传递,就是通过形参与实参之间的数据传递实现的。,例8.1、输入两个整数,求它们的最大值。求最大值用函数max实现。 main () int a, b, c;scanf(“%d,%d“, ,max(a ,b),max(x,y),return(z),计算z,x和y是形式参数,a和b是实际参数,关于形参与实参的说明: 1、在定义函数中指定的形参,在未发生函数调用时,不占内存空间。它们是动态分配的。 2、实参可以是常量、变量或表达式,在函数调用时,将实参的值传给形参变量。 3、在被定义的

5、函数中,必须指定形参的类型。如:int max(int x , int y) 4、实参与形参的类型应相同或赋值兼容。,5、C语言规定,实参变量对形参变量的数据传递是“值传递” ,既单向传递,只有实参传给形参,而不能由形参传回来给实参。 如下图:,二、函数的返回值,1、函数中的return语句返回函数的值,一个函数可以有一个以上的return语句,执行到哪一个return语句,哪个return语句就起作用。例如:max(int x, int y)return (xy? x : y ); 或max(int x,int y)if(xy) return x;else return y;,2、定义函数时

6、,应指明函数(返回值)类型,若未指名,系统认为返回值类型为int。例如:int max(int x, int y) float min(char a,char b) 3、如果函数的返回值声明与return语句中表达式的类型不同,以函数的返回值声明为准,系统将自动进行转换。,main() float a , b;int c;scanf ( “%f,%f”, ,4、只要函数定义了返回值类型,无论函数中是否有return语句,函数均返回一个值。下面语句也是合法的:,main( ) int a,b,c;a=star( );b=message( );c=star( );printf(“%d,%d,%d”

7、,a,b,c); star( ) printf(“*n“); message( ) printf(“game over!n“); ,5、为了明确规定函数不返回任何值,在函数定义中,“类型标识符”必须声明为void(无类型或称空类型)。void star( ) printf(“*n“); void message( ) printf(“game over!n“); ,8.4 函数的调用,一、函数调用的一般形式函数名(实参列表) 函数调用时,要求实参与形参个数相等,类型对应一致,实参与形参按顺序一一对应传递数据,实参表中各参数的求值顺序,C标准未作统一规定,Turbo C按自右向左的顺序求值。,二

8、、函数调用的方式 函数调用作为一个语句printstar( ); 函数作为表达式的一部分 c = 2*max(a,b); 函数的值作为一个函数的参数 m = max (a, max(b,c); printf(“%d“, max(a,b);,三、对被调函数的说明,在一个函数中调用另一个函数,需要具备那些条件: 1、被调用的函数必须已经存在。 2、使用系统预定义的函数(库函数),必须包含头文件,因为头文件中声明了库函数的原型(函数名、返回值类型及形参类型称为函数的原型)。#include “stdio.h“ #include “math.h” 3、如果使用用户自己定义的函数,而且主调函数与被调函数

9、在同一文件中,通常应该在主调函数中对被调用的函数作一个声明.,例8.2 main () float add(float x, float y); /* 对add函数的声明 */ float a,b,c; scanf(“%f,%f“, ,在main的开头声明函数原型。,函数定义和函数声明的区别定义:确立函数的功能,包括指定函数名、函数值类型、形参及其类型、函数体等,是一个完整的、独立的函数单位。声明:函数声明称为函数原型,是对已定义的函数的返回值进行类型说明,只包括函数名、函数类型及一个空括弧,不包括形参和函数体。(但通常可给出形参相关信息,在这便于编译系统进行检错,以防止可能出现的错误),函数

10、声明的一般形式 (1) 函数类型 函数名(参数类型1,参数类型2,); (2) 函数类型 函数名(参数类型1 参数名1,参数类型2 参数名2, );例 float add(float x, float y); 等价于: float add(float , float );,函数原型与函数定义中的函数首部写法上应该一致,函数类型、函数名、参数个数、参数类型和参数顺序必须一样。函数调用时:函数名、实参个数应和函数原型一致。实参类型必须于函数原型中的形参类型赋值兼容。,main () int a, b, c;scanf(“%d,%d“, ,1、返回值为整型的函数。编译系统会把第一次遇到的函数调用作为

11、函数的声明。,不需要函数声明的情况,float add(float x, float y) float z; z = x + y; return z; main () float a,b,c; scanf(“%f,%f“, ,2、被调用函数的定义出现在主调用函数之前,float add(float x, float y); main () float a,b,c; scanf(“%f,%f“, ,3、在所有函数定义之前,文件的开头,已经作了函数声明。,8.5 函数的嵌套调用,函数的嵌套调用:在一个函数的函数体内调用另一个函数。,调用一个函数过程中又调用了另一个函数,在函数的嵌套调用中,函数的执

12、行采取后调用先返回的原则。即最内层的函数调用最先返回函数值,由内到外依次返回。,例8.3求解x3-5x2+16x-80=0的根,解题步骤: 1. 取两个不同点x1,x2如果f(x1)和f(x2)符号相反,则x1,x2区间必有一个根,如果同号,则应改变x1和x2,直至异号为止 2. 连接f(x1)和f(x2),交x轴于x点,则 x=x1*f(x2)-x2*f(x1)/f(x2)-f(x1) 3. 求f(x) 4. 若f(x)与f(x1)同号,则(x,x2)有根,此时将x作为x1若f(x)与f(x2)同号,则(x,x1)有根,此时将x作为x2 5. 重复24的步骤,直至f(x)某个值,视精度要求而

13、定,x1,f(x1),x,x2,f(x2),f(x),#include “math.h” float f(float x) float y;y=(x-5.0)*x+16)*x-80;return (y); float xpoint(float x1, float x2) float x; x=(x1*f(x2)-x2*f(x1) /(f(x2)-f(x1); return (x); ,float root(float x1, float x2) float x,y,y1; y1=f(x1); do x=xpoint(x1,x2); y=f(x); if (y*y10) y1=y; x1=x;

14、elsex2=x;while (fabs(y)=0.0001);return (x); ,/*1. 从以上函数可知,所有函数均是独立的 */ /*2. 所有函数均设为 “float“ */ /*3. 所有函数均在 main() 之前定义 */ main() float x1,x2,f1,f2,x;doprintf(“input x1,x2:n“);scanf(“%f,%f“, ,main( ),调用函数root,输出根 x 结束,root函数,xpoint函数,调用函数xpoint,调用函数f,f函数,8.6 函数的递归调用,递归调用:一个函数的函数体直接或间接调用该函数本身. int f(

15、int x) int y,z; z = f(z); /*直接调用该函数本身*/ return (2*z); ,有五个人坐在一起,求第5个人多少岁。第5个人多少岁? 比第4个人大2岁。 第4个人多少岁? 比第3个人大2岁。 第3个人多少岁? 比第2个人大2岁。 第2个人多少岁? 比第1个人大2岁。 第1个人多少岁? 我10岁。 表达为: age(5) = age(4) + 2 age(4) = age(3) + 2 age(3) = age(2) + 2 age(2) = age(1) + 2 age(1) = 10; 递归表达式:,例8-4,求解过程:,用一个函数age()来求第n个人多少岁。

16、,main() int age(); /* 声明函数原型 */ printf(“%dn“,age(5); int age(int n) /* 求第n个人多少岁 */ int c; if (n=1) c = 10; else c = age(n-1) + 2; return c; ,求n的阶乘,例8-5,float fac(int n) float f;if(n0) printf(“n0,data error!“);else if(n=0|n=1) f=1;else f=fac(n-1)*n;return(f); main() int n;float y;printf(“Input a inte

17、ger number:“);scanf(“%d“, ,Hanoi问题,void move(char getone, char putone) printf(“%c-%cn“,getone,putone); void hanoi(int n,char one,char two,char three) if(n=1) move(one,three);else hanoi(n-1,one,three,two);move(one,three);hanoi(n-1,two,one,three); main() int m;printf(“Input the number of disks:“);scan

18、f(“%d“, ,例8-6,从例题中可以看到,有些问题,采用递归的方法解决,会变得非常简单,且源程序也很简洁。 一个问题要采用递归的方法解决时,要符合以下条件: 1、可以把一个问题转化为一个新问题,而新问题的解决方案仍与原问题相同,只是问题的规模不同。它们只是有规律的递增或递减。 2、可以通过转化过程使问题得到解决。 3、必须有一个明确的结束递归的条件。,8.7 数组作为函数参数,关于数组要点:设数组: int a5 1、a0、a1、a2、a3、a4表示每一个 元素 的值。 2、数组名a表示该数组在内存的起始地址。 3、可以用地址运算符&获得某个元素的地址。如&a2获得元素a2的地址.第一个元

19、素 a0的地址&a0即为数组a的起始地址。 4、数组元素作为函数的参数时,采用“值传送”即单向传送,即把元素的值传送给形式参数;数组名作为函数参数时,采用“地址传送”,即把数组的起始地址传送给形式参数。,1、数组元素作为函数的参数。 采用“值传送”即单向传送,即把元素的值传送给形式参数;,a和b为有10个元素的整型数组 比较两数组对应元素 变量n,m,k记录aibi, ai=bi, aik,认为数组ab若nk,认为数组ab若n=k,认为数组a=b,比较两数组的大小,例8-7,n=0 m=0 k=0,int large(int x,int y) int flag;if(xy) flag=1;el

20、se if(xy) flag=-1;else flag=0;return (flag); ,#include main() int a10,b10,i,n=0,m=0,k=0;printf(“Enter array a:n“);for(i=0;i10;i+)scanf(“%d“,printf(“Enter array b:n“);for(i=0;ibi %d timesnai=bi %d timesnaik) printf(“array a is larger than array bn“);else if (nk) printf(“array a is smaller than array

21、bn“);else printf(“array a is equal to array bn“); ,2、数组名可作为函数参数有一个一维数组score,内放10个学 生成 绩,求平均成绩。,float average(float array10) int i;float aver,sum=array0;for(i=1;i10;i+)sum=sum+arrayi;aver=sum/10;return(aver); ,例8-8,不起任何作用,编译系统不对此大小作任何检查。,main() float score10,aver;int i;printf(“input 10 score:n“);for(

22、i=0;i10;i+)scanf(“%f“, ,数组元素与 数组名作函数参数比较,#include void swap2(int x,int y) int z;z=x; x=y; y=z; main() int a2=10,20;swap2(a0,a1);printf(“a0=%dna1=%dn“,a0,a1); ,值传递,#include void swap2(int x ) int z;z=x0; x0=x1; x1=z; main() int a2=10,20;swap2(a);printf(“a0=%dna1=%dn“,a0,a1); ,地址传递,float average(float

23、 array, int n) int i;float aver,sum=array0;for (i=1;in;i+)sum=sum+arrayi;aver=sum/n;return(aver); main() static float score_15=98.5,97,91.5,60,55;static float score_210=67.5,89.5,99,69.5,77,89.5,76.5,54,60,99.5;printf(“the average of class A is %6.2fn“,average(score_1,5);printf(“the average of class

24、 B is %6.2fn“,average(score_2,10); ,3、用多维数组名作函数参数 例8.9 有一个3*4的矩阵,求所有元素中的最大值。,max_value(int array 4) int i,j,k,max;max=array00;for (i=0;imax)max=arrayij;return(max); main() int a34=1,3,5,7,2,4,6,8,15,17,34,12;printf(“maxvalueis%dn“,max_value(a) ); ,8.8 局部变量和全局变量,一、局部变量局部变量:在函数内部定义的变量,它只在该函数范围内有效(可以使用

25、),称为“局部变量”。,float f1 ( int a ) int b,c; main ( ) int m,n;,a、b、c有效,m、n有效,main( ) int a,b;int c;c=a+b;,c有效,a、b有效,关于局部变量的说明,1. 主函数中定义的变量也只在主函数中有效。 2. 不同函数中可以使用相同名称的变量。 3. 形参也是局部变量。 4. 复合语句中定义的变量只在本复合语句中有效。,二、全局变量全局变量:在任何函数之外定义的变量, 也称为外部变量,从定义它开始,在整个程序(所有函数)内都是有效的(或称为“可见的”,即可以使用)。,int p=1,q=5; /* 外部变量 *

26、/ float f1(int a) /* 定义函数f1 */ int b,c; char c1,c2; /* 外部变量 */ char f2(int x,int y) /* 定义函数f2 */ int i,j; main ( ) /* 主函数 */ int m,n;,全局变量c1、c2的作用范围,全局变量 p 、 q的作用范围,1、全局变量从定义它开始,在整个程序中均可以使用。因此,对于多个函数需要使用的共同变量,设计为全局变量。 2、建议少用全局变量。因为: 全局变量在整个程序运行过程中都占内存;局部变量仅在定义局部变量的函数被执行时才占内存,函数执行完释放所占内存。 全局变量使各函数互相关

27、联,结构性差。 降低程序可读性。因为全局变量的值随时可能被其他位置的程序修改,不便于阅读,使程序容易出错。 3.在同一源文件中,若外部变量与局部变量同名,则在局部变量的作用域内,外部变量不起作用。,全局变量作为公共变量,例8.10 有一个数组,内放10个学生成绩,写一个函数,求出平均分、最高分、最低分。 把平均分设计为函数average的返回值,最高分max、最低分min在函数average和主函数main中均需要使用,设计为全局变量。,float Max , Min ; float average(float array, int n) int i; float sum=array0;Max

28、=Min=array0;for(i=1;iMax) Max=arrayi;else if(arrayiMin) Min=arrayi;sum+=arrayi;return(sum/n); ,main() int i; float ave,score10;for (i=0;i10;i+)scanf(“%f“, ,局部变量与外部变量同名,int a=3,b=5; max(int a, int b) int c;c=ab?a:b;return(c); main() int a=8;printf(“max=%d“,max(a,b); ,运行结果:max=8,例、写出下面程序的执行结果。 int k=3

29、; 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=12k=7,8.9 动态存储变量和静态存储变量,一、变量的存储类别从变量的作用域(可见性)看,变量分为:全局变量局部变量,静态外部变量(本文件引用) 外部变量(允许其它文件引用),自动变量(动态局部变量)(本函数内有效) 静态局部变量(离开函数,值仍保持) 寄存器变量(离开函数,值就消失),从变量存在的时间

30、(生存期)上看,变量分为:静态存储变量:程序运行期间分配固定的内存空间。 动态存储变量:程序运行期间不固定分配内存空间,仅在需要时分配,不需要时就释放。静态存储区动态存储区计算机内存一方面供操作系统使用(称为系统区),另方面供用户程序使用(称为用户区),静态局部变量外部变量(全局变量),自动局部变量 寄存器变量 形式参数,变量的属性:数据类型和数据的存储类别. 变量的存储类别:指数据在内存中的存储方法,有两大类:静态存储动态存储具体包括四种:自动的(auto)寄存器的(register)静态的(static)外部的(extern),二、auto变量,1、局部变量自动的(auto)存储方式。函数

31、的局部变量,不专门说明为静态变量,都是动态分配存储空间,存储在动态存储区。对它们的分配和释放是由编译系统自动处理的,因此,称为自动变量。 不作专门说明的局部变量,均是自动变量。也可以用关键字auto作出明确说明。 例、int f(int a) auto int b,c=3; /* 自动变量 */ int x,y=2; /*未作专门说明,隐含为自动变量*/ ,三、 用static声明局部变量在函数调用结束后,其所占内存空间不被释放,其值保留原值.则应该指定该局部变量为“局部静态变量”.用关键字static作专门说明。 在定义静态局部变量时不赋初值的话,系统自动赋值为0或空字符(对字符变量)。,i

32、nt 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); 输出结果是:7 8 9 调用函数f 调用时初值 调用结束时的值 b自动 c静态 b自动 c静态 a+b+c 第1次 0 3 1 4 7 第2次 0 4 1 5 8 第3次 0 5 1 6 9,例8.12求1到5的阶乘,int fac(int n) static int f=1;f

33、=f*n;return( f ); main() int i;for (i=1;i=5;i+)printf(“%d! =%dn“,i,fac(i); ,1、只有局部自动变量和形参可以作为寄存器变量,其他变量不可以(全局变量、局部静变量不可以)。 2、CPU的寄存器数目有限,不能定义太多的寄存器变量。 3、Turbo C系统把寄存器变量仍然放在内存中,因此,不能提高速度。,四、register寄存器局部变量对于一些频繁使用的变量,可以放在CPU内部的寄存器中,以提高访问这些变量的速度。这些变量称为“寄存器变量”。寄存器变量用关键字register声明。,五、用extern声明外部变量,外部变量(

34、全局变量)均采用静态存储方式,放在程序的静态存储区。 1、全局变量:在任何函数之外定义的变量,称为外部变量,从开始定义的位置开始,到整个程序结束都是有效的。 2、全局变量未被初始化,系统自动赋初值0。,(一)用extern扩展外部变量作用域,(1)同一个文件中,在外部变量定义点之前的函数想引用该外部变量,应该在引用之前用extern对该变量作“外部变量声明”。,int max(int x,int y) int z;z=xy?x:y;return(z); main() extern A,B;printf(“%dn“,max(A,B); int A=13,B=-8;,外部变量定义,用extern扩

35、展外部变量的,(2)对于由几个文件组成的C程序,当一个源文件A要引用另一个源文件B中的全局变量时,要用extern将该全局变量的作用域扩展到源文件B中。,/*file1.c*/ int a; main() int power(int);int b=3,c,d,m;printf(“enter the number a and its power:n“);scanf(“%d,%d“, ,/*file2.c*/extern int a; power(int n) int i,y=1;for (i=1;i=n;i+)y*=a;return(y); ,给定b,输入a、m, 求a*b和am。,(二)全局变

36、量使用static修饰符,其作用域只在它定义的源程序中。 (三)函数外全局变量只能定义1次!,存储类别小结,/*file1.c*/ int a; main() int power(int);int b=3,c,d,m;printf(“enter the number a and its power:n“);scanf(“%d,%d“, ,/*file2.c*/extern int a; power(int n) int i,y=1;for (i=1;i=n;i+)y*=a;return(y); ,运行一个多文件程序,在集成环境tc20中,建立工程管理文件example.prj:file1.cfile2.c 编译运行example.prj,file1.c file1.obj file2.c file2.obj,example.exe,编译,编译,连接,不建立工程管理文件example.prj,把file1.c改为:# include “file2.c”int a;main(),

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 中等教育 > 小学课件

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报