《C语言程序设计》第七章函数课件.ppt

上传人(卖家):三亚风情 文档编号:3367617 上传时间:2022-08-24 格式:PPT 页数:72 大小:1.76MB
下载 相关 举报
《C语言程序设计》第七章函数课件.ppt_第1页
第1页 / 共72页
《C语言程序设计》第七章函数课件.ppt_第2页
第2页 / 共72页
《C语言程序设计》第七章函数课件.ppt_第3页
第3页 / 共72页
《C语言程序设计》第七章函数课件.ppt_第4页
第4页 / 共72页
《C语言程序设计》第七章函数课件.ppt_第5页
第5页 / 共72页
点击查看更多>>
资源描述

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 指针与函数指针与函数7.8 7.8 变量的存储类别变量的存储类别7.9 7.9 模块化程序设计方法模块化程序设计方法 补充:如何运行一个多文件的程序补充:如何运行一个多文件的程序 第七章第七章 函数与模块化程序设计方法函数与模块化程序设计方法 一个较大的程序一般应分为若干个程序模块,每一个模块用来实现一个特定的功能一个C程序可由一

2、个主函数和若干个函数构成。由主函数调用其他函数,其他函数也可以互相调用。同一个函数可以被一个或多个函数调用任意多次。下图是一个程序中函数调用的示意图:maingedefghhicba函数概述函数概述 main()/*主函数主函数 */print_star();/*调用调用print_star函数画函数画*/print_message();/*调用调用print _message函数写字函数写字*/print_star();/*调用调用print_star函数画函数画*/print_star()/*定义定义print_star函数函数*/prinf(“n*”);print_message()/*

3、定义定义print_message函数函数*/prinf(“n Hello!”);函数调用实例:函数调用实例:运行结果:运行结果:*Hello!*说明:(1)一个源程序文件由一个或多个函数组成。一个源程序文件 是一个编译单位,即以源程序为单位进行编译,而不是以 函数为单位进行编译。(2)一个C程序由一个或多个源程序文件组成。一个源文件可 以为多个C程序公用。(3)C程序的执行从main函数开始,调用其他函数后流程回到 main函数,在main函数中结束整个程序的运行。main函数 是系统定义的。(4)所有函数都是平行的,即在定义函数时是互相独立的,一 个函数并不从属于另一函数,函数间可以互相调

4、用,但不 能调用main函数。(5)从用户使用的角度看,函数有两种:标准函数标准函数,即库函数。这是由系统提供的,用户不必自己 定义这些函数,可以直接使用它们。用户自己定义的函数。用以解决用户的专门需要。(6)从函数的形式看,函数分两类:无参函数无参函数。有参函数有参函数。在调用函数时,在主调函数和被调用函数之间 有数据传递。也就是说,主调函数可以将数据传给被调用 函数使用,被调用函数中的数据也可以带回来供主调函数 使用。1、无参函数的定义形式类型标识符类型标识符 函数名()函数名()声明部分声明部分 语句语句 2、有参函数定义的一般形式 类型标识符类型标识符 函数名(形式参数表列)函数名(形

5、式参数表列)声明部分声明部分 语句语句 函数的定义函数的定义例如:int max(int x,int y)int z;z=xy?x:y;return(z);3、可以有、可以有“空函数空函数”它的形式为:类型说明符类型说明符 函数名()函数名()例如:dumy()4、对形参的声明的传统方式 在老版本C语言中,对形参类型的声明是放在函数定义的第2行,也就是不在第l行的括号内指定形参的类型,而在括号外单独指定,例如:int max(x,y)int x,y;int z;z=xy?x:y;return(z);一般把这种方法称为传统的对形参的声明方式,而把前面介绍过的方法称为现代的方式。Turbo C和目

6、前使用的多数C版本对这两种方法都允许使用,两种用法等价。1、形式参数和实际参数、形式参数和实际参数 在定义函数时函数名后面括弧中的变量名称为“形形式参数式参数”,在主调函数中调用一个函数时,函数名后面括弧中的参数(可以是一个表达式)称为“实际参数实际参数”。函数的参数和返回值函数的参数和返回值 例:调用函数时的数据传递main()int a,b,c;scanf(“%d%d”,&a,&b);c=max(a,b);printf(“Max is%d”,c);int max(int x,int y)int z;z=xy?x:y;return(z);运行情况:运行情况:7,8 Max is 8(1)在定

7、义函数中指定的形参,在未出现函数调用时,它们并 不占内存中的存储单元。只有在发生函数调用时,函数 max中的形参才被分配内存单元。在调用结束后,形参所 占的内存单元也被释放。(2)实参可以是常量、变量或表达式,如:max(3,a+b);但要求它们有确定的值。在调用时将实参的值赋给形参 (如果形参是数组名,则传递的是数组首地址而不是数组 的值)。关于形参与实参的说明:关于形参与实参的说明:(3)在被定义的函数中,必须指定形参的类型。(4)实参与形参的类型应相同或赋值兼容。(5)C语言规定,实参变量对形参变量的数据传递是“值传递”,即单向传递,只由实参传给形参,而不能由形参传回来给 实参,在调用函

8、数时,给形参分配存储单元,并将实参对 应的值传递给形参,调用结束后,形参单元被释放,实参 单元仍保留并维持原值。函数的返回值函数的返回值(1)函数的返回值是通过函数中的return语句获得的。return 语句将被调用函数中的一个确定值带回主调函数中去。return 语句后面的括弧也可以不要,如:return z;return后面的值可以是一个表达式。int max(int x,int y)return(xy?x:y);(2)函数值的类型。在定义函数时指定函数值的类型。例如:int max(float x,float y)函数值为整型char letter(char c1,char c2)函数

9、值为字符型double min(int x,int y)函数值为双精度型 C语言规定,凡不加类型说明的函数,一律自动按整型处理。在定义函数时对函数值说明的类型一般应该和return语句中的表达式类型一致。例 返回值类型与函数类型不同。main()float a,b;int c;scanf(“%f,%f,”,&a,&b);c=max(a,b);printf(“”Max is%dn”,c);max(float x,float y);float z;/z为实型变量/z=xy?x:y;return(z);运行情况如下:1.5,2.5Max is 2(3)如果函数值的类型和return语句中表达式的值不

10、一致,则 以函数类型为准。对数值型数据,可以自动进行类型转 换。即函数类型决定返回值的类型。(4)如果被调用函数中没有return语句,并不带回一个确定的、用户所希望得到的函数值,但实际上,函数并不是不带回 值,而只是不带回有用的值。带回的是一个不确定的值。(5)为了明确表示“不带回值”,可以用“void”定义“无类型”(或称“空类型”)1、函数调用的一般形式 函数名(实参表列);函数名(实参表列);如果是调用无参函数,则“实参表列”可以没有,但括弧不能省略,如果实参表列包含多个实参,则各参数间用逗号隔开。实参与形参的个数应相等,类型应一致。实参与形参按顺序对应,一一传递数据。如果实参表列包括

11、多个实参,对实参求值的顺序并不是确定的,有的系统按自左至右顺序求实参的值,有的系统则按自右至左顺序。许多 C版本(例如 Turbo C和 MS C)是按自右而左的顺序求值。函数的调用函数的调用 2、函数调用的方式 按函数在程序中出现的位置来分,可以有以下三种函数调用方式:(1)函数语句 把函数调用作为一个语句。如:printstar();(2)函数表达式 函数出现在一个表达式中,这种表达式称为函数表达式。这时要求函数带回一个确定的值以参加表达式的运算。例如:c=2*max(a,b);(3)函数参数函数调用作为一个函数的实参。例如:m=max(a,max(b,c);3、对被调用函数的声明和函数原

12、型 在一个函数中调用另一函数(即被调用函数)需要具备的条件(1)首先被调用的函数必须是已经存在的函数(是库函数或用 户自己定义的函数)。(2)如果使用库函数,一般还应该在本文件开头用include命 令将调用有关库函数时所需用到的信息“包含”到本文件中 来。例如,前几章中已经用过的 include(3)如果使用用户自己定义的函数,而且该函数与调用它的函 数(即主调函数)在同一个文件中,一般还应该在主调函 数中对被调用的函数作声明声明,即对编译系统声明将要调用 此函数,并将有关信息通知编译系统。例例 对被调用的函数作声明对被调用的函数作声明main()float add(float x,floa

13、t y);/对被调用函数的声明/float a,b,c;scanf(“%f,%f”,&a,&b);c=add(a,b);printf(“sum is%f”,c);float add(float x,float y);/函数首部/float z;/函数体/z=x+y;return(z);运行情况如下:3.5,6.5sum is 10.000000在函数声明中也可以不写形参名,而只写形参的类型。如:float add(float,float););在C语言中,以上的函数声明称为函数原型(function prototype)。它的作用主要是利用它在程序的编译阶段对调用函数的合 法性进行全面检查。函

14、数原型的一般形式为 函数类型函数类型 函数名(参数类型函数名(参数类型1,参数类型,参数类型2)函数类型函数类型 函数名(参数类型函数名(参数类型1 参数名参数名1,参数类型,参数类型2 参数名参数名2,)第种形式是基本的形式。为了便于阅读程序,也允许在函数原型中加上参数名,就成了第种形式。但编译系统不检查参数名。因此参数名是什么都无所谓。说明:如果在函数调用之前,没有对函数作声明,则编译系统会把第一次遇到的该函数形式(函数定义或函数调用)作为函数的声明,并将函数类型默认为int型。如果函数类型为整型,可以在函数调用前不必作函数声明。但是使用这种方法时,系统无法对参数的类型做检查。若调用函数时

15、参数使用不当,在编译时也不会报错。因此,为了程序清晰和安全,建议都加以声明为好。如果被调用函数的定义出现在主调函数之前,可以不必加以 声明。如果已在所有函数定义之前,在函数的外部已做了函数声明,则在各个主调函数中不必对所调用的函数再作声明。例如:char letter(char,char);/以下3行在所有函数之前,且在函数外部/float f(float,float);int i(float,float);main()/不必声明它所调用的函数/char letter(char c1,char c2)/定义letter函数/float f(float x,float y)/定义f函数/int

16、i(float j,float k)/定义i函数/例题:例题:写出下列程序的输出结果写出下列程序的输出结果(1)#include swap(int a,int b)int temp;temp=a;a=b;b=temp;main()int x=7,y=11;printf(x=%d,ty=%dn,x,y);printf(swapped:n);swap(x,y);printf(x=%d,ty=%dn,x,y);答案:x=7 y=11swapped:x=7 y=11(2)void swap(int*p1,int*p2)int p;p=*p1;*p1=*p2;*p2=p;main()int x=7,y=

17、11;printf(“x=%d,y=%dn”,x,y);printf(“swapped:n”);swap(&x,&y);printf(“x=%d,y=%dn”,x,y);答案:x=7 y=11swapped:x=11 y=7分析:通过对上面两程序,理解两种参数传递方式的区别:值传递方式 函数调用时,为形参分配单元,并将实参的值复制到形参中;调用结束,形参单元被释放,实参单元仍保留并维持原值。特点是形参与实参占用不同的内存单元,单向传递。地址传递 函数调用时,将数据的存储地址作为参数传递给形参,特点是形参与实参占用同样的存储单元,“双向”传递,实参必须是地址常量或变量,形参是地址变量。C语言的函

18、数定义都是互相平行、独立的,也就是说在定义函数时,一个函数内不能包含另一个函数。C语言不能嵌套定义函数,但可以嵌套调用函数,也就是说,在调用一个函数的过程中,又调用另一个函数。main函数函数a函数函数b函数函数调用调用a函数函数调用调用b函数函数结束结束函数的嵌套调用函数的嵌套调用 例 编一个程序计算下列函数值;要求为函数p(i)、s(n)、f(x,y)均编写一个用户函数,x、y由主函数输入。f(x,y)=s(x)s(y)其中s(n)=p(i)=p(1)+p(2)+p(n),p(i)=i!ni=1float p(long i)long k,j;for(k=j=1;j=i;j+)k=k*j;r

19、eturn(float)(k);float s(long n)float sum=0.0;long k;for(k=1;k1)的递归调用函数。float p(long n)if(n1 1 n=0,14、例Hanoi塔问题 古代有一个梵塔,塔内有三个座a、b、c,开始时a座有三个盘子,盘子大小不等,大的在下,小的在上,要把这三个盘子从a座移到c座,但每次只允许移动一个盘,且在移动过程中在三个座上都始终保持大的在下,小的在上。a b c 算法:先把n1个盘子从a柱移到b柱(借助c柱);把第n个盘子从a柱移到c柱;把b柱上的n-1个盘子借助a柱移到c柱。void move(char x,char y

20、)printf(“%c%cn”,x,y);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 diskes:”);scanf(“%d”,&m)printf(“The step to moving%3d diskes:n”,m);hanoi(m,A,B,C);运行结果:input the nu

21、mber of diskes:3The step to moving 3 diskes:ACABCBACBABCAC1、数组元素作函数实参、数组元素作函数实参 例 有两个数组a、b,各有 10个元素,将它们对应地逐个相比(即 a0与b0比,a1与b1比)。如果a数组中的元素大于b数组中的相应元素的数目多于b数组中元素大于a数组中相应元素的数目(例如,aibi 6次,biai 3次,其中 i每次为不同的值),则认为a数组大于b数组,并分别统计出两个数组相应元素大于、等于、小于的次数。程序如下:数组作为函数参数数组作为函数参数 main()int large(int,int);int a10,b1

22、0,i,n=0,m=0,k=0;printf(“enter array a:n”);for(i=0;i10;i+)scanf(“%d”,&ai);printf(“n”);printf(“enter array b:n”);for(i=0;i10;i+)scanf(“%d”,&bi);printf(“n”);for(i=0;ibi%d timesnai=bi%d timesnaik)printf(“array a is larger than array bn”);else if(ny)flag=1;else if(xbi 4 timesai=bi 1 timesai bi 5 timesarr

23、ay a is smaller than array bfloat average(float array10)int i;float aver,sum=0;for(i=0;i10;i+)sum=sum+arrayi;aver=sum/10;return(aver);2、数组名可作函数参数、数组名可作函数参数 例 有一个一维数组score,内放10个学生成绩,求平均成绩。程序如下:main()float score10,aver;int i;printf(“intput 10 scores:n”)for(i=0;i10;i+)scanf(“%f”,&scorei);printf(“n”);av

24、er=average(score);printf(“average score is%5.2f”,aver);运行结果:input 10 scores:100,56,78,98.5,76,87,99,67.5,75,97average score is 83.40说明:(1)用数组名作函数参数,应该在主调函数和被调用函数分别 定义数组。(2)实参数组与形参数组类型应一致(今都为float型),如不 一致,结果将出错。(3)实参数组和形参数组大小可以一致也可以不一致,C编译 对形参数组大小不做检查,只是将实参数组的首地址传给 形参数组。(4)形参数组也可以不指定大小,在定义数组时在数组名后面 跟

25、一个空的方括弧,为了在被调用函数中处理数组元素的 规模,可以另设一个参数,传递数组元素的个数。(5)用数组名作函数实参时,不是把数组的值传递给形参,而 是把实参数组的起始地址传递给形参数组,这样两个数组 就共占同一段内存单元。变量的作用域:变量的作用域:局部变量与全局变量的应用局部变量与全局变量的应用 1、局部变量:、局部变量:在一个函数内部定义的变量是内部变量,只在 本函数内部有效。2、全局变量:、全局变量:在函数外定义的变量称为外部变量,外部变量 是全局变量,全局变量可以为本文件中其它函 数共用,它的有效范围为从定义变量的位置开 始到本源文件结束。例:例:变量的作用域。#include s

26、tdio.hint n=65;void print()printf(%dn,n);main()printf(%dn,n);print();程序运行为6565我们可以看到,定义了全局变量,无论是主函数还是自定义的函数,都可以使用全局变量。如果我们把程序改成这样:#include stdio.hvoid print()printf(%dn,n);main()int n=65;printf(%dn,n);print();则在编译时,系统会提示在print()函数内的变量n未定义。其实在这个程序中,主函数中定义的变量n是一个局部变量,它的范围只是在主函数内,不能用在主函数之外的地方。例例 有一个一维数

27、组,内放10个学生成绩,写一个函数,求 出平均分、最高分和最低分。程序如下:float Max=0,Min=0;float average(float array,int n)int i;float aver,sum=array0;Max=Min=array0;for(i=1;iMax)Max=arrayi;else if(arrayiMin)Min=arrayi;sum=sum+arrayi;aver=sum/n;return(aver);main()float ave,score10;int i;for(i=0;ib?a:b;return(c);main()int a=8;/a为局部变量/

28、printf(“%d”,max(a,b);形参a、b作用范围a、b作用范围局部变量a作用范围全局变量b的作用范围运行结果为:8静态存储方式:指在程序运行期间分配固定的存储空间的方式。动态存储方式:指在程序运行期间根据需要进行动态的分配存 储空间的方式。用户使用的存储空间可以分为三部分,如右图所示:程序区 静态存储区 动态存储区用 户 区 动态存储方式与静态存储动态存储方式与静态存储 数据分别存放在静态存储区和动态存储区中。全局变量全部存放在静态存储区中,在程序开始执行时给全局变量分配存储区,程序执行完毕就释放。程序执行过程中它们占据固定的存储单元,而不是动态地进行分配和释放。在动态存储区中存放

29、以下数据:函数形式参数。自动变量(未加static声明的局部变量)函数调用时的现场保护和返回地址等。局部静态变量局部静态变量1局部静态变量(1)定义格式:static 数据类型 内部变量表;(2)存储特点3)何时使用局部静态变量1)需要保留函数上一次调用结束时的值。2)变量只被引用而不改变其值。1)静态内部变量属于静态存储。在程序执行过程中,即使所在函数调用结束也不释放。换句话说,在程序执行期间,静态内部变量始终存在,但其它函数是不能引用它们的。2)定义但不初始化,则自动赋以(整型和实型)或0(字符型);且每次调用它们所在的函数时,不再重新赋初值,只是保留上次调用结束时的值!例:例:打印1到5

30、的阶乘值。int fac(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);运行结果为:1!12!23!64!245!120(1)定义格式定义格式:auto 数据类型 变量表;(2)存储特点存储特点 1)自动变量属于动态存储方式。在函数中定义的自动变量,只在该函数内有效;函数被调用时分配存储空间,调用结束就释放。在复合语句中定义的自动变量,只在该复合语句中有效;退出复合语句后,也不能再使用,否则将引起错误。2)定义而不初始化,则其值是不确定的。如果初始化,则赋初值操

31、作是在调用时进行的,且每次调用都要重新赋一次初值。3)由于自动变量的作用域和生存期,都局限于定义它的个体内(函数或复合语句),因此不同的个体中允许使用同名的变量而不会混淆。即使在函数内定义的自动变量,也可与该函数内部的复合语句中定义的自动变量同名。建议:建议:系统不会混淆,并不意味着人也不会混淆,所以尽量少用同名自动变量!auto变量变量例:自动变量与静态局部变量的存储特性。例:自动变量与静态局部变量的存储特性。void auto_static(void)int var_auto=0;/*自动变量:每次调用都重自动变量:每次调用都重新初始化新初始化*/static int var_static

32、=0;/*静态局部变量:只初始化静态局部变量:只初始化1次次*/printf(“var_auto=%d,var_static=%dn”,var_auto,var_static);+var_auto;+var_static;main()int i;for(i=0;i=a&c=A&c=Z)return(1);else return(0);main()int i,num=0;char str255;printf(Input a string:);gets(str);for(i=0;stri!=0;i+)if(isalp(stri)num+;puts(str);printf(num=%dn,num);

33、2、用直接递归调用计算整数和:1+2+3+4+n。答案:long sum(int n)if(n1)return(1);return(sum(n-1)+n);3、输入长方体的长(l)、宽(w)、高(h),求长方体体积及正、侧、顶三个面的面积。提示:利用全局变量计算长方体的三个面的面积答案:int s1,s2,s3;int vs(int a,int b,int c)int v;v=a*b*c;s1=a*b;s2=b*c;s3=a*c;return v;main()int v,l,w,h;clrscr();printf(ninput length,width and height:);scanf(%

34、d%d%d,&l,&w,&h);v=vs(l,w,h);printf(v=%d,s1=%d,s2=%d s3=%dn,v,s1,s2,s3);分析:要注意局部变量和全局变量的区别:分析:要注意局部变量和全局变量的区别:局部变量是内部变量,在函数内定义,只在本函数内有效。局部变量是内部变量,在函数内定义,只在本函数内有效。另外对于局部变量要注意:另外对于局部变量要注意:main中定义的变量只在中定义的变量只在main中有效中有效不同函数中同名变量,占不同内存单元不同函数中同名变量,占不同内存单元形参属于局部变量形参属于局部变量可定义在复合语句中有效的变量可定义在复合语句中有效的变量局部变量可用存储类型:局部变量可用存储类型:auto,register,static,(默认为,(默认为auto)全局变量是外部变量,在函数外定义,可为本文件所有函数共用,全局变量是外部变量,在函数外定义,可为本文件所有函数共用,有效范围为从定义变量的位置开始到本源文件结束,及有有效范围为从定义变量的位置开始到本源文件结束,及有extern说明的其它源文件。说明的其它源文件。

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

当前位置:首页 > 办公、行业 > 各类PPT课件(模板)
版权提示 | 免责声明

1,本文(《C语言程序设计》第七章函数课件.ppt)为本站会员(三亚风情)主动上传,163文库仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。
2,用户下载本文档,所消耗的文币(积分)将全额增加到上传者的账号。
3, 若此文所含内容侵犯了您的版权或隐私,请立即通知163文库(发送邮件至3464097650@qq.com或直接QQ联系客服),我们立即给予删除!


侵权处理QQ:3464097650--上传资料QQ:3464097650

【声明】本站为“文档C2C交易模式”,即用户上传的文档直接卖给(下载)用户,本站只是网络空间服务平台,本站所有原创文档下载所得归上传人所有,如您发现上传作品侵犯了您的版权,请立刻联系我们并提供证据,我们将在3个工作日内予以改正。


163文库-Www.163Wenku.Com |网站地图|