




已阅读5页,还剩80页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1,第5章函数,C语言程序设计,大连理工大学出版社,第5章函数,5.1函数的作用5.2函数定义和函数调用5.3函数调用中的参数传递5.4函数的嵌套调用和递归调用5.5变量的作用域和存储类别本章小结,2,2019/12/2,3,5.1函数的作用,程序结构清晰,可读性好。减少重复编码的工作量。可多人共同编制一个大程序,缩短程序设计周期,提高程序设计和调试的效率。,使用函数的好处,2019/12/2,4,例5.1函数调用的简单例子。,voidmyprint()inti=0;for(i=1;i=18;i+)printf(*);printf(“n”);,voidmyprint_n(intn)inti=0;for(i=1;ib)max=a;elsemax=b;if(max0。,#include#includelongmyfac(intn)inti=0;longy=1;for(i=1;iy?x:y;return(z);,voidmain()inta,b,c;scanf(%d,%d,程序运行情况如下:5,18maxis18,x:,y:,b:,a:,18,5,5,18,z:18,2019/12/2,19,关于形参和实参的说明:,函数未被调用时,形参并不占内存中的存储单元。只有在发生函数调用时,形参才由系统分配存储单元(与实参单元是不同的单元),并将实参值传递到形参单元中;在执行被调函数的过程中,形参单元被访问或被重新赋值,但均与实参单元无关;函数调用结束后,形参单元被系统释放,而实参单元仍然保留且值不变。在实参与形参之间传递数据采用的是单向的“值传递”方式。,2019/12/2,20,实参可以是常量、变量或表达式。例如:max(a+b,8);实参的类型与相对应的形参的类型应相同或赋值兼容。如果实参为实型而形参为整型,或者相反,则按不同类型数值的赋值规则进行转换。假如,调用子函数max时,实参a的值为5.9,而形参x为整型,则系统会将实数5.9转换成整数5后传递给形参x。,2019/12/2,21,4.函数的返回值,return语句的两个功能:(1)返回值。(2)终止被调函数的执行,使流程返回主调函数。,return(表达式);,return语句的语法格式如下:,2019/12/2,22,return语句的使用形式:return后面的表达式,可用圆括号也可不用。例如:return(c);与returnc;是等价的。return(ab?a:b);与returnab?a:b;是等价的。一个函数若没有返回值时,return后面不带表达式,即:return;如果不需要从被调函数带回函数值,则被调函数中可以不要return语句。,2019/12/2,23,一个函数可以有多个return语句,即多个出口。例如:intsign(floatx)if(x0)return(1);elseif(x=0)return(0);elsereturn(-1);,2019/12/2,24,2)函数的返回值类型,函数的类型决定函数返回值的类型。例如,下面是3个函数定义中的函数首部:intmax(floatx,floaty)/*函数值为整型*/charlet(charc1,charc2)/*函数值为字符型*/floatmin(intx,inty)/*函数值为浮点型*/函数返回值类型一般应和return语句中的表达式类型一致,否则以函数的类型为准。,2019/12/2,25,例5.6求两个整数中的大者。,intmax(floatx,floaty)/*定义函数为整型*/floatz;/*定义变量z为单精度型*/z=xy?x:y;return(z);/*将z值作为函数值返回*/voidmain()floata,b;intc;scanf(%f,%f,程序运行情况如下:6.5,8.5maxis8,2019/12/2,26,对于无返回值的函数,函数的类型最好说明为void型,它表示“无类型”或“空类型”。若无返回值的函数省略void,函数将返回一个不确定的值。这时在被调用函数的函数体中可以没有return语句,也可以有不带返回值的return语句,2019/12/2,27,例5.7打印n个“#”的函数。voidspc(intn)或:inti;for(i=0;in;i+)printf(%c,#);return;,voidspc(intn)inti;for(i=0;in;i+)printf(%c,#);,无返回值的函数中使用return语句的示例:,main()spc(5);,main()spc(5);,2019/12/2,28,C语言规定,一般要求被调用函数定义在前、调用在后。若被调用函数定义在后、调用在前,可以运用函数原型声明语句来解决这个问题。,2019/12/2,29,5.被调函数声明与函数原型,格式1:类型名函数名(参数类型1参数名1,参数类型2参数名2,参数类型n参数名n);格式2:类型名函数名(参数类型1,参数类型2,参数类型n);,例如:voidprint(intmumber,charsex,floatscore);大体上可猜出这是一个输出学号、性别和成绩的函数,而若写成:voidprint(int,float,char);则无从知道参数的含义。,2019/12/2,30,例5.8对被调函数的声明。,voidmain()floatsub(floatx,floaty);/*对被调函数sub的声明*/floata,b,c;scanf(%f,%f,程序运行情况如下:3.6,6.5subis-2.900000,2019/12/2,31,(3)如果在文件的开头(在所有函数之前)对本文件中要调用的所有函数进行了声明,则在各函数中不必对其所要调用的函数再作声明。,charletterf(char,char);floatfloatf(float,float);intintegerf(int,int);voidmain()/*调用letterf、floatf和integerf函数*/*不必对它所调用的函数进行声明*/charletterf(charcl,charc2)floatfloatf(float,float)intintegerf(int,int),2019/12/2,注意区分函数声明和函数定义(不是一回事):函数定义:对函数功能的确立,是一个完整的,独立的函数单位;函数声明:旨在把函数的名字、函数类型以及形参的类型、个数和顺序通知编译系统,不包含函数体。例:函数定义函数声明,voidmyprint()inti=0;for(i=1;i=18;i+)printf(*);printf(“n”);,floatsub(floatx,floaty);,charletterf(char,char);floatfloatf(float,float);,33,5.3函数调用中的参数传递,根据参数值类型的不同,“值传递”又分为“数值传递”和“地址传递”两种类型。,5.3.1简单变量作函数参数,当形参是简单变量时,实参与形参之间采用“数值传递”方式。实现实参单元向形参单元的单向传递。,2019/12/2,34,例5.9编一程序,将一整数乘以10后显示出来。,intmult(intn)n*=10;/*形参n的值被改变*/return(n);voidmain()intnumber;intresult;number=668;result=mult(number);/*以实参number去调用mult函数*/printf(“number=%dn”,number);/*实参number的值不会printf(result=%dn,result);被改变*/,程序运行结果为:number=668result=6680,number:,n:,668,668,6680,2019/12/2,35,例5.10输出Fibonacci数列的前17项。,intfib(inta,intb)intc;c=a+b;a=b;b=c;returnc;voidmain()inti,first=0,second=1;printf(%3d%3d,first,second);for(i=1;iy)flag=1;elseif(xy)flag=-1;elseflag=0;return(flag);,2019/12/2,40,voidmain()intlarge(intx,inty);inta10,b10,i,n=0,m=0,k=0;for(i=0;ik)printf(arrayaislargerthanarraybn);elseif(nk)printf(arrayaissmallerthanarraybn);elseprintf(arrayaisequaltoarraybn);/*n记录a比b大的元素个数k记录a比b小的元素个数m记录a与b相等的元素个数*/,2019/12/2,41,2.数组名作函数参数,数组名表示数组在内存中的起始地址。例如:数组a在内存中从2000地址开始存放,则a的值为2000。2000是地址值,是指针类型的数据(第7中将介绍指针类型),不能把它看成是整型或其他类型数据。实参是数组名,形参也应定义为数组形式,形参数组的长度可以省略,但不能省,否则就不是数组形式了。实参与形参采用“地址传递”方式,形参与实参占用同一存储区域,inta3=1,2,3;,2000,2019/12/2,42,(1)一维数组名作为函数参数,以下4种情形是等效的:实参和形参都是数组名;实参为指向数组的指针变量,形参为数组名;实参为数组名,形参为指向数组的指针变量;实参和形参都是指向数组的指针变量。,2019/12/2,43,实参数组名代表一个已分配存储单元的数组的地址,实质上是一个指针常量,因此,无论用数组名还是用指向数组的指针变量作为实参,向形参传递的均是数组的地址。形参是接收从实参传递过来的数组地址的,形参应该是一个指针变量。实际上,C编译就是把形参数组名作为指针变量来处理的。,2019/12/2,44,例5.13一维数组名作为函数参数的情形。,#defineN9voidoutput(inta,intn)inti;for(i=0;in;i+)printf(%5d,ai);printf(n);,voidmain()intxN,i;for(i=0;iN;i+)xi=2*i;output(x,N);/函数调用,实参x,形参a,x0,x1,x2,x3,x4,x5,x6,x7,x8,a0,a1,a2,a3,a4,a5,a6,a7,a8,2019/12/2,45,例5.14编写函数统计一个一维数组(10个元素)中非0元素的个数。,intsolve(intb,intn)intsum=0,i;for(i=0;in;i+)if(bi!=0)sum+;return(sum);,voidmain()inta10,num,i;for(i=0;i10;i+)scanf(%d,实参a,形参b,a0,a1,a2,a3,a4,a5,a6,a7,a8,b0,b1,b2,b3,b4,b5,b6,b7,b8,b9,a9,2019/12/2,46,例5.15编一函数实现数组逆置。,数组逆置是将数组的第一个元素值放到最后一个位置,第二个元素值放到倒数第二个位置,直到最后一个元素值放到第一个位置。(数组有个元素),a:0123456789,a:9876543210,a0=0,an=N-1,2019/12/2,47,#defineN9voidmain()voidfun(intaN);intaN,i;for(i=0;iN;i+)scanf(%d,voidfun(intxN)inta0,an,temp;a0=0;an=N-1;while(a0an)temp=xa0;xa0=xan;xan=temp;a0+;an-;return;,2019/12/2,48,(2)多维数组名作为函数参数,多维数组名作函数参数时,被调函数中对形参数组的定义中,可以指定每一维的长度,也可以不指定第一维的长度,但其余各维的长度都必须指定。如:check(floata10,intn),下面的参数说明都是不正确的:floata;或:floata10;,2019/12/2,49,例5.16从键盘为一个5x5整型数组输入数据,找出并显示主对角线上元素的最小值。,intsmall(inta55)inti,vm;vm=a00;for(i=1;iaii)vm=aii;return(vm);,voidmain()inti,j,vmin;intarray55;for(i=0;iz)?r1:z;return(r2);intmin(intx,inty,intz)intr;r=(x1),10(n=1),递归结束条件,age(n),2019/12/2,65,intage(intn)intc;if(n=1)c=10;elsec=age(n-1)+2;return(c);voidmain()printf(%dn,age(5);,运行结果如下:18,2019/12/2,66,例5.23用递归方法求解斐波纳契(Fibonacci)数列。,0,1,1,2,3,5,8,13,21,34,为斐波纳契数列。从中可以看出,斐波纳契数列第n项的值是其前两项的和,这就是递归公式;而当n=0和1时,斐波纳契数列项就是n值本身,这就是递归结束条件。可用如下递归公式表述:,fib(n-1)+fib(n-2)(n2),0(n=0),递归结束条件,fib(n),1(n=1或n=2),2019/12/2,67,voidmain()intfib(intn);/*函数声明*/inti;for(i=0;i20;i+)/*求斐波纳契数列前20项*/if(i%5=0)printf(n);printf(%12d,fib(i);/*输出斐波纳契数列第i项的值*/printf(n);intfib(intn)/*定义求斐波那契数列第n项值的函数*/if(n=0|n=1)/*递归结束条件*/returnn;elsereturnfib(n-2)+fib(n-1);/*递归调用*/,2019/12/2,68,程序运行结果如下:01123581321345589144233377610987159725844181,2019/12/2,5.5变量的作用域和存储类别,所谓变量的作用域,是指变量在程序中的有效范围。如果一个程序只由一个main函数组成,其变量的作用域情况比较简单,显然其变量只在main函数中有效。但是一般一个C程序都包含多个函数,那么定义在A函数中的变量可否在B函数中使用?这涉及变量的作用域问题。从作用域角度,变量分为局部变量和全局变量。所谓变量的存储类别,是指变量在内存中的存储方法。通常C语言程序在计算机内占用的存储空间可分为3部分,分别被称之为程序区、静态存储区、动态存储区。其中,程序区中存放的是可执行程序的机器指令,静态存储区中存放的是需要占用固定存储单元的变量,动态存储区中存放的是不需要占用固定存储单元的变量。不同的存储方法将影响变量值的存在时间(即生存期)。从存储类别角度,变量有动态存储和静态存储两种类型。,69,2019/12/2,5.5.1局部变量及其存储类型,在函数内部定义的变量称为局部变量,局部变量的作用域仅仅局限于定义它的函数。例如:charfunc1(inta,chars1,chars2)/*函数func1*/intb,c;/*a、s1、s2、b、c有效*/floatfunc2(floatm,floatn,inta)/*函数func2*/floatx,y,z;/*m、n、a、x、y、z有效*/intb,c;/*b、c有效*/,70,2019/12/2,5.5.1局部变量及其存储类型,局部变量有3种存储类型:自动类(auto)、静态类(smtie)和寄存器类(register)。1.自动类变量在函数内定义的变量,如果不显式地指定其存储类型,系统会将其默认为自动类变量。在定义自动类变量时,应该在定义变量的类型名前面使用auto关键字,如:autofloatf;auto是C语言编译系统默认的存储类型,所以关键字auto可以省略。自动类变量是在动态存储区内分配单元的(因而也称其为动态变量),函数返回时,编译系统将释放这些存储单元,即当函数调用结束时,自动类变量不复存在。,71,2019/12/2,例5.24编一程序,每调用一次函数,显示一次自动变量中的内容,然后给其值加1。,#includevoidtest_auto()intv=0;printf(v=%dn,v);+v;voidmain()inti;for(i=0;i4;i+)test_auto();,72,程序运行情况如下:v=0v=0v=0v=0,2019/12/2,5.5.1局部变量及其存储类型,2.静态类变量如果希望在函数调用结束后,仍然保留函数中定义的局部变量的值,则可以将该局部变量定义为静态局部变量。在定义静态局部变量时,应该在定义变量的类型名前面使用static关键字,如:staticintx;静态局部变量在静态存储区中分配存储单元,在整个程序运行期间都不释放,因此,每次函数调用结束后,它的值并不消失,其值能够保持连续性。静态局部变量是在编译阶段赋初值的,且只赋一次初值,以后调用函数时不再赋初值,而是保留上一次函数调用时的结果。,73,2019/12/2,例5.25编一程序,每调用一次函数,显示一次静态局部变量中的内容,然后给其值加1。,#includevoidtest_static()staticintv=0;printf(v=%dn,v);+v;voidmain()inti;for(i=0;i4;i+)test_static();,74,2019/12/2,程序运行情况如下:v=0v=1v=2v=3,例5-26使用自动存储变量和静态存储变量,#includeintmyfun();/*对函数myfun的声明*/voidmain()inti=0,a=0;for(i=1;i=1)printf(*);n-;printf(n);voidmain()inta=1000;myprint(a);运行程序时输出1000个“*”。,77,2019/12/2,78,有关寄存器变量的进一步说明:只有局部自动变量和形参可以定义为寄存器变量。不能定义任意多个寄存器,否则自动按auto来处理。寄存器没有地址,若n是寄存器变量,/*定义全局变量*/floatfunc1(floatz)/*定义函数func1*/floatx1,x2;intm=100,n=50;/*定义全局变量*/charfunc2(charc1,charc2)/*定义函数fun
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025中介服务合同劳动合同
- 水疗养生中心技师聘用与客户满意度提升协议
- 智能化生产线整体转让及技术服务合同
- 2025年设计委托合同标准文本
- 养殖场经营管理商业计划书范文
- 版画制作工节假日后复工安全考核试卷含答案
- 财务共享服务中心运营管理规范
- 智能家居项目市场推广方案模板
- 有色矿石磨细工节假日后复工安全考核试卷含答案
- 船舶客运员节假日后复工安全考核试卷含答案
- 2025年“学宪法、讲宪法”主题活动知识竞赛题库及答案
- 2024年毕节威宁自治县招聘城市社区工作者真题
- 2025年度2025年少先队知识测试题及答案
- GB/T 15234-2025塑料平托盘
- 山东省汽车维修工时定额(T-SDAMTIA 0001-2023)
- GB/T 12363-2021锻件功能分类
- 水调歌头-公开课教学设计 省赛一等奖
- 《番茄工作法图解》课件
- 报价单模板及范文(通用十二篇)
- 蒂森克虏伯电梯MC2-C调试介绍
- 苏教版三年级数学上册《间隔排列》作业纸(大组教研)
评论
0/150
提交评论