




已阅读5页,还剩50页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第七章 函数,7.1 概述,一、C程序的构成,从结构上:任何复杂结构的程序都可分为三种基本结构。,顺序结构、选择结构、循环结构的组合。,从组织形式:最简单的程序也要有三个层次构成,C程序源文件 - C函数 - C语句,所有函数都是平行的,即在定义函数时是互相独立的,一个函数并不从属于另一个函数,即函数不能嵌套定义,只可以互相调用,但不能调用main函数。,二、C函数的两种类型,1、标准函数,即库函数,这是由系统提供的,用户不必自己定义这些函数,可以直接使用。,2、自定义函数,用户自己定义的函数,以解决用户的专门需要。,三、使用函数解决的几个问题,1、提高程序设计效率,2、实现程序的模块化,提高可读性,方便编写、修改。,3、函数可供反复调用,避免一些程序段的重复书写。,四、函数的使用,1、函数之间的关系,main()函数: 主导函数,程序运行从main()开始,也从此处结束,运行中可以调用其它函数。,其它函数: 可以互相调用函数、自调用函数,不能调用main()。,2、使用参数,入口参数: 主调函数向被调函数传递的数据-实参、形参。,出口参数: 被调函数向主调函数传递的数据-返回值。,7.2 函数的定义,问题:,1、被调函数如何使用主调函数中的数据。,2、假设被调函数有办法使用主调函数中的数据,如何保证被调函数和主调函数中数据类型的一致。,3、如何将被调函数的工作结果告诉主调函数。,4、假设有办法将被调函数的工作结果告诉主调函数,如何保证数据类型的一致性。,一、函数定义的一般形式(P79-P83),类型说明符 函数名(形式参数列表) P79 形式参数类型说明 函数体 ,例如: int max(x,y) int x,y; 函数体 ,二、函数的参数 (P82),1、形(式)参(数)与实(际)参(数),形参:为构造函数而存在,不具备确切值,其值在函 数被调用时,从主调函数的实参获得。,实参:与实际问题紧密联系的具体数据。,实参数值:可以是常量、变量或表达式,但要求他们 有确定的值。在调用时将实参的值赋给形参 变量。,形参数值:变量,其数量、类型与实参一致。,2、实参 - 形参数据传递,函数调用,传值调用,传址调用,(单独的变量或数组元素),传值调用函数的数据传递过程:,调用函数时:为形参分配临时存储单元,运行被调用函数时:实参数据装入形参临时存储单元,形 参携带实参数据参与运算。,调用结束:形参临时单元被释放,形参数据失效,实参数 据不变。这就是所谓的单值传递。,函数的形参和实参具有以下特点: (1)、形参变量只有在被调用时才分配内存单元,在调用结束时, 即刻释放所分配的内存单元。因此,形参只有在函数内部有效。 函数调用结束返回主调函数后则不能再使用该形参变量。,(2)、实参可以是常量、变量、表达式、函数等, 无论实参是何种类型的量,在进行函数调用时,它们都必须具有确定的值, 以便把这些值传送给形参。 因此应预先用赋值,输入等办法使实参获得确定值。,(3)、实参和形参在数量上,类型上,顺序上应严格一致, 否则会发生“类型不匹配”的错误。,(4)、函数调用中发生的数据传送是单向的。 即只能把实参的值传送给形参,而不能把形参的值反向传送给实参。 因此在函数调用过程中,形参的值发生改变,而实参中的值不会变化。,main() int a,b; scanf(“%d,%d“, ,int swap(x,y) int x,y; int t; t=x;x=y;y=t; ,请指出程序运行的结果。,三、函数值(P80、P83),函数的值是指函数被调用之后, 执行函数体中的程序段所取得的并返回给主调函数的值。,1、函数的值只能通过return语句返回主调函数。,return 语句的一般形式为: return 表达式; 或者为: return (表达式);,该语句的功能是计算表达式的值,并返回给主调函数。,有时函数可产生多个运行结果, 但return()语句只能返回一个数据。 在函数中允许有多个return语句,但每次调用只能有一个return 语句被执行, 因此只能返回一个函数值。,注意:,Return语句有两个作用:一是结束函数的运行,二是带着运算的结果(表达式的值)返回主调函数。,如果省略了return语句,当函数中所有语句都执行完后,也会自动返回主调函数。,2、函数值(回传值)的类型与被调用函数的类型说明,函数调用语句 被调函数类型 回传值类型,在定义函数时,需要指定函数的类型: 例如: int max(x,y); doubel a(c1,c2); 等等,注意: (1)、如函数值为整型,在函数定义时可以省去类型说明。,(3)、回传值类型和函数类型矛盾时,则以函数类型为准,自动进行类型转换。,(2)、不返回函数值的函数,可以明确定义为“空类型”, 类型说明符为“void”。 可定义为: void s(int n) ,7.3 函数的调用(P82),一、函数调用的一般形式,函数名 (实参表列),其中,实参以 “,” 分隔,形、实参数数量相等,类型一致。,从主调函数和被调函数之间数据传送的角度看又可分为无参函数和有参函数两种。,(1)无参函数 函数定义、函数说明及函数调用中均不带参数。 主调函数和被调函数之间不进行参数传送。 (2)有参函数 在函数定义及函数说明时都有参数, 称为形式参数(简称为形参)。进行函数调用时,主调函数将把实参的值传送给形参,供被调函数使用。,二、函数调用的各种形式,1、直接调用,把函数调用作为一个语句: 例如: char c=a; putchar(c);,这时不要函数带回值,只要求函数完成一定的操作。,2、构成表达式语句 函数作为表达式中的一项出现在表达式中,以函数返回值参与表达式的运算。这种方式要求函数是有返回值的。 例如: z=2*max(x,y); 是一个赋值表达式,把max的返回值赋予变量z。,3、函数作为另一个函数调用的实际参数出现。 这种情况是把该函数的返回值作为实参进行传送,因此要求该函数必须是有返回值的。 例如: printf(“%d“,max(x,y); 即是把max调用的返回值又作为printf函数的实参来使用的。,例如:max(max(a,b),max(c,d);,三、对被调函数的说明 (P83),函数说明在主调函数中调用某函数之前应对该被调函数进行说明, 这与使用变量之前要先进行变量说明是一样的。 在主调函数中对被调函数作说明的目的是使编译系统知道被调函数返回值的类型, 以便在主调函数中按此种类型对返回值作相应的处理。,1、被调函数为库函数 对库函数的调用不需要再作说明, 但必须把该函数的头文件用include命令包含在源文件前部。,2、用户自定义的函数 一般应该在主调函数中对被调函数的返回值的类型做说明。,对被调函数的说明也有两种格式, 一种为传统格式,其一般格式为: 类型说明符 被调函数名();,另一种为现代格式,其一般形式为: 类型说明符 被调函数名(类型 形参,类型 形参);,3、以下几种情况时可以省去主调函数中对被调函数的函数说明,(1)、 如果被调函数的返回值是整型或字符型时, 可以不对被调函数作说明,而直接调用。这时系统将自动对被调函数返回值按整型处理。,(2)、当被调函数的函数定义出现在主调函数之前时, 在主调函数中也可以不对被调函数再作说明而直接调用。,(3)、如在所有函数定义之前, 在函数外预先说明了各个函数的类型,则在以后的各主调函数中,可不再对被调函数作说明。,例如:写一个判断素数的函数,在主函数输入一个整数,输出是否为素数的信息。,main() int a,c; scanf(“%d“,int ss(y) int y; int z=0,i; for (i=2; iy; i+) if (y%i = 0) z=1; break; return(z);,例一: 由键盘输入任意两个整数x、y,编写一个函数mypow()用来求x的y次方。,main() int x,y,z; scanf(“%d,%d“,int mypow(int x,int y) int i,p; p=1; for(i=1;i=y;i+) p=p*x; return p;,例二: 已知e=1+1/1!+1/2!+ 1/3!+ 1/n!,试用公式求e的近似值,要求累计加所有不小于106的项值,用函数fun()完成任何数的阶乘。,int fun(int i) int j,k; k=1; for(j=1;j=i;j+) k=k*j; return k;,main() int i=1; float e=0.0,n=1.0; while(n1.0e-6) n=1.0/fun(i); i+; e=e+n; printf(“%f“,e); getch();,7.4 函数的嵌套调用 (P194),C语言的函数定义都是互相平行的、独立的,即在定义函数时,一个函数内不能包含另一个函数。,C语言不能嵌套定义函数,但可以嵌套调用函数。即在调用一个函数过程中,又调用另一个函数。,即被调函数可以作为主调函数去调用其它函数。,7.5 函数的递归调用(P198),在递归调用中, 主调函数又是被调函数。执行递归函数将反复调用其自身。 每调用一次就进入新的一层。,在调用一个函数的过程中又出现直接或间接地调用该函数本身,称为函数的递归调用。,int f(int x) int y; z=f(y); return(z);,例如:,例如: 有5个人坐在一起,问第五个人多少岁?他说比第4个人大2岁。问第4个人岁数,他说比第3个人大2岁。问第三个人,又说比第2人大两岁。问第2个人,说比第一个人大两岁。最后问第一个人,他说是10岁。请问第五个人多大?,特点:问题的第n项的求解,依赖于n-1项的求解结果。,main() int c,n; scanf(“%d“, ,int a(m) int m; int z; if(m=1) z=10; else z=a(m-1)+2; return(z); ,举例:利用递归方法求 n!,递归公式 n!=,1 n=0,1,n*(n-1)! n1,从递归函数的程序编写角度看,有两个关键点:,1、递归的出口: 即递归的结束条件,到何时不再递归调用下去。,2、递归表达式:如 fact(n)=n*fact(n-1),7.6 数组作为函数参数,一、数组元素作为函数参数,数组元素作为实参的函数调用与变量作为实参的函数调用参数的使用上完全相同。,二、用数组名作为函数参数,数组名作为函数参数时不进行值传送而进行地址传送。,main() int a; scanf(“%d“, ,add(b) int b; b=b+1;,main() int a10,i; for(i=0;i10;i+) scanf(“%d“, ,add(b) int b10; int i; for(i=0;i10;i+) bi=bi+1; ,总结:,3、形、实参数组类型应一致保证正确读取数据。,2、形参数组通过获得实参数组首地址获得实参数组数据。,1、数组名作为形、实参的函数调用-传址调用。,4、形、实参数组长度应相同保证读取全部有效数据。,5、数组名作为形、实参是传址调用。形参数组中各元素的值发生变化会使实参数组元素的值同时发生变化。,main() static char str100; gets(str); inverse(str); puts(str); getch(); ,例:写一个函数,使输入的一个字符串按反序存放,在主函数中输入和输出字符串。,inverse(str) char str ; char t; int i; for(i=0;istrlen(str)/2;i+) t=stri; stri=strstrlen(str)-i-1; strstrlen(str)-i-1=t; ,7.7 局部变量和全局变量 (P86),局部变量也称为内部变量。局部变量是在函数内作定义说明的。其作用域仅限于函数内, 离开该函数后再使用这种变量是非法的。,1、 主函数中定义的变量也只能在主函数中使用,不能在其它函数中使用。同时,主函数中也不能使用其它函数中定义的变量。,一、局部变量,2、形参变量是属于被调函数的局部变量,实参变量是属于主调函数的局部变量。,3、允许在不同的函数中使用相同的变量名,它们代表不同的对象,分配不同的单元,互不干扰,也不会发生混淆。,4、在一个函数的内部,可以在复合语句中定义变量,这些变量值只能在本复合语句中有效,这些变量在离开复合语句时失效,释放内存变量。,二、全局变量,全局变量也称为外部变量,它是在函数外部定义的变量。 它不属于哪一个函数,它属于一个源程序文件。其作用域是从定义变量的位置开始到本源文件结束。,全局变量作为函数间数据联系的补充通道,主调函数通过全局变量使用被调函数中的多个数据。,被调函数通过全局变量使用主调函数中的数据。,3、外部变量可加强函数模块之间的数据联系, 但是又使函数要依赖这些变量,因而使得函数的独立性降低。从模块化程序设计的观点来看这是不利的, 因此在不必要时尽量不要使用全局变量。,1、如果定义外部变量的位置在引用变量的函数之后,应该用extern进行说明。,2、在同一源文件中,允许全局变量和局部变量同名。在局部变量的作用域内,全局变量不起作用。,例如:有一个一维数组,内放10个同学成绩,写一个函数,求出平均分、最高分和最低分。,float max,min; main() int i; float aver,a10; float average(); for(i=0;i10;i+) scanf(“%f“,float average(a) float a10; float aver,sum=0; int i; max=min=sum=a0; for(i=1;imax) max=ai; if(aimin) min=ai; sum=sum+ai; aver=sum/10; return aver;,7.8 动态存储变量和静态存储变量 (P88),变量的生存期: 自动变量和静态变量。,变量的作用域: 全局变量和局部变量。,动态变量: 在程序运行期间根据需要动态的分配存储空间 的方式。,静态变量: 在程序运行期间分配固定的存储空间的方式。,一、auto变量 (P86),动态存储变量是在程序执行过程中,使用它时才分配存储单元, 使用完毕立即释放。,局部变量、函数的形式参数即属于此类存储方式。,auto int a,b=100;,auto在大多数的情况下省略不写的。,二、用static声明局部变量 (P88),静态局部变量是在编译时赋初值,即只赋初值一次,在程序运行时它已有初值。以后每次调用函数时不再重新赋初值而只是保留上次函数调用结束时的值。,动态变量赋初值,不是在编译时进行的,而是在函数调用时进行,每次调用函数重新给一次初值,相当于执行一次赋值。,注意:,1、对静态局部变量,编译时自动赋初值0或0。而对自动变量来说,如果不赋初值则它的值是一个不确定的值。,2、虽然静态局部变量在函数调用结束
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 高中英语 Unit 5 Music Writing说课稿 新人教版必修2
- 口腔保健知识培训体会课件
- 高二数学学考试题及答案
- 高2物理统考试卷及答案
- 第2课 输入与保存文章教学设计小学信息技术电子工业版内蒙古五年级下册-电子工业版(内蒙古)
- 保健艾灸知识培训课件
- 守墓工作专业知识培训课件
- 保健知识培训结业班总结课件
- 学龄前小孩知识培训内容课件
- 2025年外贸业务员高级面试指南与模拟题答案集萃
- 基本公共卫生服务培训
- 新员工入职人事制度培训
- 健康中国2030课件
- 2025年《数据化运营》课程标准
- 破产清算造价咨询合同协议
- 村干部值班制度
- 员工积分制度考核范本
- 口腔护士述职报告
- 白兰地酒水知识
- 2025年度乡村振兴规划设计合同样本
- 电力工程投标文件中的质量保证及售后服务计划范文
评论
0/150
提交评论