版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第7章函数7.1函数概述7.2函数的使用7.3函数的参数传递7.4函数的嵌套和递归调用本章主要内容7.5变量的作用域7.6变量的存储类别7.7内部函数与外部函数7.8函数程序设计示例7.1函数概述7.1.1函数的概念C语言的函数与数学的函数十分相似。在数学中,函数“y=f(x)”表示对于自变量x的每个给定值,总是按照一定的规律f给出它的结果y。在C语言程序中,可用以下命名为func()的函数来实现这个数学函数的功能。intfunc(intx){inty;
y=x*x+3*x+4;
return(y);}37.1函数概述7.1.2函数的分类1.根据函数自身形式划分(1)无参函数(2)有参函数2.从用户角度划分(1)标准函数(即库函数)(2)自定义函数43.C程序的总体结构main(){…funa();…funb();…}funa(){…fun1();…}funb(){…fun2();…fun3();…}fun1(){…}
fun2(){…}
}
fun3(){…}
图7-1C程序总体结构57.2函数的使用7.2.1函数的定义和声明1.函数定义的格式类型名函数名([函数参数表])/*函数首部,[]中的内容表示可选项*/{
说明部分;/*函数体*/
执行部分;}注意:在函数定义时,函数名要反映函数的功能;每一个函数要完成一个具体的功能;函数定义不能嵌套,也就是说在函数体内不能再定义函数。6【例7-1】定义一个求两个整数和的函数。函数定义如下:intsum(intx,inty){ intt; /*说明部分*/ t=x+y; /*以下两条语句是执行部分*/return(t);}7【例7-2】定义输出一串字符的函数。函数定义如下:
voidhello(){printf{"hello,world\n"};}8注意:在函数定义时,函数名要反映函数的功能;每一个函数要完成一个具体的功能;函数定义不能嵌套,也就是说在函数体内不能再定义函数。2.函数参数【例7-3】定义一个求n个整数和的函数。函数定义如下:intsumn(inta[],intn)/*n代表数据个数,数组a存放被求和的n个整数*/{inti,t=0;for(i=0;i<n;i++)t=t+a[i];return(t);}说明:前面我们学习过数组,在定义数组时要指定数组的长度,但数组作为形
参时其长度可省略。93.函数的类型和返回值【函数的类型在函数名前面给出,表明该函数返回值的类型。函数返回值是指函数被调用之后,用return语句返回给主调函数的值。return语句的格式为:return表达式;或return(表达式);或return;/*只能用于void返回值类型的函数*/107.2.2函数的调用1.函数调用方式函数调用的一般形式为:
函数名(实参表列)2.被调函数的声明函数声明的一般格式为:
类型名函数名(函数参数表);11【例7-4】求两个实数的最大值。#include<stdio.h>intmain(){floatmax(floatx,floaty);/*对被调函数的声明,x和y名称可以省略,也可放在main()前声明*/floata,b,c;printf("请输入两个实数:");scanf("%f%f",&a,&b);c=max(a,b);/*函数调用*/printf("最大值为:%f\n",c);return0;}floatmax(floatx,floaty)/*max函数的定义*/{floatz;if(x>y)z=x;elsez=y;return(z);}127.3函数的参数传递7.3.1值传递当普通变量作为函数参数时,一旦发生函数调用,系统给形式参数分配存储空间,按数据复制的方式,实参把数据传递给形参。这种数据传递是单向的值传送,形参与实参分别占用不同的存储空间。调用结束后,被调函数中所有变量(包含形参)的存储空间释放,不能再被使用,其值也不会再传回给实参。13例如,调用例7-2中sum()函数的完整程序如下:#include<stdio.h>intsum(intx,inty){intt;t=x+y;return(t);}intmain(){inta,b,c;printf("请输入两个整数:");scanf("%d%d",&a,&b);c=sum(a,b);printf("sum=%d\n",c);return0;}程序运行结果:请输入两个整数:1020↙sum=30147.3函数的参数传递7.3.2地址传递在C程序中经常需要把数组的全部元素传递到另一函数中处理。当数组元素较多时,如果仍采用“值传递”的方式,把数组的每个元素作为一个参数传递到另一函数中,必然要使用大量的参数。此时,采用“地址传递”方式可以很好解决数组中大量数据在函数间的传递问题,也就是用数组名作为函数参数。数组名作参数传递时,形参应使用数组或后面要学习到的指针类型,并且在主调函数和被调函数中分别进行定义。15例如,调用例7-3中sumn()函数的完整程序如下:#include<stdio.h>intsumn(inta[],intn)/*数组的大小不用给出,其本质是一个指针变量*/{inti,t=0;for(i=0;i<n;i++)t=t+a[i];return(t);}intmain(){intx[10],i,sum;printf("请输入10个整数:");for(i=0;i<10;i++)scanf("%d",&x[i]);sum=sumn(x,10);printf("10个数的和为:%d\n",s);return0;}16程序运行结果:请输入10个整数:12227384546570281980↙10个数的和为:5077.4函数的嵌套和递归调用7.4.1函数的嵌套调用【例7-5】求组合数,其中 (注:“!”是阶乘运算)分析:由于运算式多次用到阶乘运算,所以把阶乘运算定义成一个阶乘函数jc(),供其他函数多次调用。17程序如下:#include<stdio.h>intjc(intn)/*阶乘函数*/{intt=1;inti;for(i=1;i<=n;i++)t=t*i;return(t);} intzhs(intm,intn) /*组合数函数*/{intx,y,z;x=jc(m); /*调用阶乘函数jc()*/y=jc(n);z=jc(m-n);return(x/(y*z));}intmain(){intm,n;printf("请输入整数m和n(m>=n):");scanf("%d%d",&m,&n);printf("组合数为:%d\n",zhs(m,n));/*调用组合数函数zhs()*/return0;}18程序运行结果:请输入整数m和n(m>=n):52↙组合数为:107.4.2函数的递归调用【例7-6】设计一个递归函数计算n!。分析:n!除了可表示为1×2×3×…×n之外,还可用以下式子表示:1 当n=0或1时n!=n×(n-1)! 当n>1时如果用jc(n)代表n!,可用下面的递归公式表示:n×jc(n-1) 当n>1时1 当n=0或1时jc(n)=19n=【例7-7】有5个人坐在一起,问第5个人多少岁,他说比第4个人大2岁,问第4个人多少岁,他说比第3个人大2岁,问第3个人多少岁,他说比第2个人大2岁,问第2个人多少岁,他说比第1个人大2岁,问第1个人多少岁,他说10岁。请问第5个人多少岁?分析:设第n个人年龄为f(n),则:f(5)=f(4)+2f(4)=f(3)+2……f(2)=f(1)+2f(1)=10据此可列出式子:
10 n=1f(n)=f(n-1)+2 n>120程序如下:#include<stdio.h>intf(intn){inta;if(n==1)a=10;elsea=f(n-1)+2;returna;}intmain(){printf("第5个人的年龄为:%d岁\n",f(5));return0;}程序运行结果:第5个人的年龄为:18岁217.5变量的作用域7.5.1局部变量【例7-8】阅读下列程序,注意同名的局部变量的使用。#include<stdio.h>voidfun(){inti;/*函数func的变量i*/for(i=0;i<3;i++)printf("fun......i=%d\n",i);}intmain(){inti;/*主函数的变量i*/for(i=0;i<3;i++){printf("main......i=%d\n",i);fun();}return0;}22程序运行结果:main......i=0fun......i=0fun......i=1fun......i=2main......i=1fun......i=0fun......i=1fun......i=2main......i=2fun......i=0fun......i=1fun......i=27.5.2全局变量【例7-9】用函数实现两个变量值的交换。#include<stdio.h>intswap(intx,inty){intt;t=x;x=y;y=t;}intmain(){inta,b;printf("请输入两个整数a和b:");scanf("%d%d",&a,&b);swap(a,b);printf("a=%d,b=%d\n",a,b);return0;}23程序运行结果:请输入两个整数a和b:1020↙a=10,b=207.6变量的存储类别在C语言中,变量的存储类型决定了变量的保留时间和作用范围,共有四种存储类型:自动(auto)、静态(static)、寄存器(register)和外部(extern)。变量的保留时间又称为生存期,从时间角度,可将变量分为静态存储和动态存储两种:(1)静态存储是指变量存储在内存的静态存储区,在编译时就分配了存储空间,在整个程序的运行期间,该变量占有固定的存储单元,程序结束后,这部分空间才释放,变量的值在整个程序中始终存在。(2)动态存储是指变量存储在内存的动态存储区,在程序的运行过程中,只有当变量所在的函数被调用时,编译系统才临时为该变量分配一段内存单元,函数调用结束,该变量空间释放,变量的值只在函数调用期存在。变量的作用范围又称为作用域,从空间角度,可以将变量分为全局变量和局部变量,在上一小节已做过介绍。247.6变量的存储类别1.自动变量(auto)函数中的局部变量,如果不专门声明为static(静态)的存储类别,都是动态的分配存储空间,都是自动变量(如函数的形参,函数内的局部变量,复合语句内的局部变量)。257.6变量的存储类别2.静态变量(static)static修饰的局部变量,生命周期延长,该变量不随函数结束而结束。虽然静态局部变量在函数调用结束后仍然存在,但其他函数是不能引用它的。因为它是局部变量,只在自身的作用域范围内起作用。静态局部变量有以下特点:(1)初始化:只在第一次调用该函数时进行初始化。对于静态局部变量,编译时自动赋初值0(对数值型变量)或空字符'\0'(对于字符变量)。而对于自动变量来说,它的值时一个不确定的值。(2)记忆性:后序调用时,该变量使用前一次函数调用完成之后保存的值。(3)存储位置:不会存储在栈上,放在数据段(静态存储区内)。267.6变量的存储类别3.寄存器变量(register)如果有一些变量频繁使用,则存取变量的值要花费不少时间。为提高执行效率,允许将局部变量的值放到CPU的寄存器中,需要用时直接从寄存器取出参加运算,不必再到内存中去存取。由于寄存器的存取速度远高于内存的存取速度,因此这样做可以提高执行效率。这种变量就叫做寄存器变量,用关键字register作声明。27说明:在现代的编译器优化技术中,register关键字的使用已经不常见了。编译器通常能够根据代码的上下文自动进行寄存器分配,并且能够更好地进行优化。7.6变量的存储类别4.外部变量(extern)外部变量,即全局变量,是在函数的外部定义的,它的作用域为从变量定义处开始,到本程序文件的末尾。如果外部变量不在文件的开头定义,其有效的作用范围只限于定义处到文件末尾。如果在定义点之前的函数想引用该外部变量,则应该在引用之前用关键字extern对该变量进行“外部变量声明”,表示该变量是一个已经定义的外部变量。有了此声明,就可以从“声明”处起,合法地使用该外部变量。通常的,用extern声明外部变量,扩展程序文件中的作用域。注意extern不是变量定义,只是声明一个定义在别处的变量。287.7内部函数与外部函数7.7.1内部函数内部函数是指限制只能在本文件中进行调用的函数,也称静态函数。内部函数的定义格式如下:static类型名函数名(参数表){
函数体}297.7内部函数与外部函数7.7.2外部函数外部函数是可以被其他文件中的函数调用的函数。外部函数的定义格式如下:extern类型名函数名(参数表){
函数体}30【例7-10】编程计算学生考试的平均分。分析:假设有50位学生,考试成绩由键盘输入,然后计算其平均分后输出,下面用多文件程序实现该算法,程序如下:文件file1.c中的内容:#include<stdio.h>intmain(){externvoidenter();/*外部函数的说明*/externfloataverage();/*外部函数的说明*/floatscore[50],aver;printf("请输入50个成绩:");enter(score,50);aver=average(score,50);printf("平均成绩为%.2f\n",aver);return0;}31文件file2.c中的内容:externvoidenter(floata[],intn)/*外部函数的定义*/{inti;for(i=0;i<n;i++)scanf("%f",&a[i]);}32文件file3.c中的内容:staticfloatsumn(floata[],intn)/*内部函数的定义*/{inti;floats=0;for(i=0;i<n;i++)s=s+a[i];return(s);}externfloataverage(floata[],intn)/*外部函数的定义*/{floatsum,aver;sum=sumn(a,n);aver=sum/n;return(aver);}337.7内部函数与外部函数7.7.3多文件编程在DEV-C++5.11环境下,创建多文件程序,实现多文件编译的步骤如下:第一步:创建各个源程序文件。可以由不同人分别创建,然后把建好的同一程序的各个源文件存放在指定目录(最好是同一个目录,这样好找),如把例7-11中file1.c、file2.c和file3.c文件保存在D:\Test目录下。第二步:建立项目。选择“File→New→Project…”,选择“ConsoleApplication”,给项目命名为“multifile”,位置为“D:\Test\multifile”,如图7-6所示。34图7-6建立项目35第三步:将源程序文件添加到工程。选择“Project→AddToProject…”,选择源程序文件所在路径,把源程序文件(file1.c、file2.c、file3.c)逐个插入到工程,如图7-7所示。图7-7源程序文件插入到工程36第四步:像一个文件程序那样编译、连接、运行程序,项目结构、file1.c、file2.c和file3.c的内容如图7-8、7-9和7-10所示。图7-8项目结构及file1.c文件内容37图7-9file2.c文件内容38图7-10file3.c文件内容397.8函数程序设计示例【例7-11】求20以内的素数,要求编写一个判断素数的函数。分析:素数是指只能被1和自身整除的自然数。由于20以内的素数很多,需要对每个数进行判断,可以设计一个判断素数的函数多次调用。判断素数的函数需要通过参数从主函数得到一个数,经过判断,是素数返回1,不是素数返回0。主函数则用循环控制1~20的整数,调用判断素数函数,确定是否输出。程序如下:40#include<stdio.h>intprime(intm) /*判断素数函数prime()*/{inti,k=1;if(m==1)return0; /*1不是素数返回0*/for(i=2;i<m;i++){if(m%i==0){k=0;break;}}returnk; /*是素数返回1,否则返回0*/}41intmain(){intx;printf("20以内的素数:");for(x=1;x<20;x++){if(prime(x)==1)printf("%5d",x);}printf("\n");return0;}程序运行结果:20以内的素数:235711131719427.8函数程序设计示例【例7-12】写两个函数,分别求两个整数的最大公约数和最小公倍数,用主函数调用这两个函数,并输出结果,两个整数由键盘输入。分析:可以用辗转相除法求最大公约数。设两数为a、b(a>b),求a和b最大公约数(a,b)的步骤如下:用a除以b,得a÷b=q......r1(0≤r1)。若r1=0,则(a,b)=b;若r1≠0,则再用b除以r1,得b÷r1=q......r2(0≤r2);若r2=0,则(a,b)=r1,若r2≠0,则继续用r1除以r2,……如此下去,直到余数为0为止。其最后一个除数即为(a,b)。如求(8,6),首先用8除以6得余数为2;然后用6除以2,得余数为0。则(8,6)=2。最大公约数求出,则最小公倍数=a×b/最大公约数。如8和6的最小公倍数为(8×6)/2=24。43#include<stdio.h>inthcf(inta,intb)/*求最大公约数函数*/{ intt,r;if(b>a){t=a;a=b;b=t;}while((r=a%b)!=0){a=b;b=r;}return(b);}intlcd(inta,intb)/*求最小公倍数函数*/{return(a*b/hcf(a,b));/*调用函数hcf()*/}程序如下:44intmain(){inta,b,h,l;printf("请输入两个正整数:");scanf("%d%d",&a,&b);h=hcf(a,b);printf("%d和%d的最大公约数为:%d\n",a,b,h);/*输出最大公约数*/l=lcd(a,b);printf("%d和%d的最小公倍数为:%d\n",a,b,l);/*输出最小公倍数*/return0;}45程序运行结果:请输入两个正整数:2416↙24和16的最大公约数为:824和16的最小公倍数为:487.8函数程序设计示例【例7-13】编写一函数,实现把一个数组中的值逆序存放。分析:要对一个数组中的元素进行操作,需要数组名作函数的参数进行地址传递。实现一组数据的逆序存放可采用首尾元素互换的方法。程序如下:46#include<stdio.h>voidinverse(intb[],intn){inti,j,t;for(i=0,j=n-1;i<j;i++,j--){ t=b[i];b[i]=b[j];b[j]=t;}} intmain(){inta[10],i;printf("请输入10个整数:");for(i=0;i<10;i++)scanf("%d",&a[i]);inverse(a,10);printf("逆序存放后为:");for(i=0;i<10;i++)printf("%d",a[i]);return0;}47程序运行结果:请输入10个整数:12345678910↙逆序存放后为:109876543217.8函数程序设计示例【例7-14】汉诺塔问题。古代印度布拉玛庙里僧侣们玩一种称为汉诺塔的游戏,据说游戏结束就标志着世界末日的到来。游戏的装置是一块铜板,上面有三根杆,最左杆自下而上、由大到小顺序串有64个金盘子,呈一个塔形,如图7-11所示。游戏要求把左边杆上的金盘子全部移到最右边的杆上,条件是一次只能移动一个盘子,并且不允许大盘子在小盘子上面。48abc图7-11汉诺塔示意图49分析:假定僧侣们要把n个盘子按题中的规定由a杆借助b杆移到c杆。模拟这一过程的算法称为hanoi(n,a,b,c)。那么,很自然的想法是:第一步:先把a杆上面的n-1个盘子设法借助c杆移动到b杆上,记做hanoi(n-1,a,c,b)。第二步:把第n个盘子从a杆移到c杆。第三步:把b杆上的n-1个盘子借助a杆移到c杆,记做hanoi(n-1,b,a,c)。上述三步描述了一个汉诺塔游戏的递归算法。程序如下:50#include<stdio.h>intmain(){intn;voidhanoi(intn,chara,charb,charc); /*被调函数的说明*/printf("请输入要搬动的盘子个数:");scanf("%d",&n);printf("搬动的顺序为:\n");hanoi(n,'a','b','c');return0;}voidhanoi(intn,chara,charb,charc){if(n==1)/*已知*/printf("%c->%c\n",a,c);else/*递推*/{hanoi(n-1,a,c,b);hanoi(1,a,b,c);hanoi(n-1,b,a,c);}}51程序运行结果:请输入要搬动的盘子个数:3↙搬动的顺序为:
a->ca->bc->ba->cb->ab->ca->c7.8函数程序设计示例【例7-15】最大子数组问题。一个数组有N个元素,求连续子数组的最大和,并返回其在原数组中的索引位置。例如,[-1,2,1]的最大连续子数组为[2,1],其和为3,索引位置为1和2(数组下标从0开始)。输入描述:输入一个n(n<100000),表示数组的长度,接下来输入n个数。输出要求:最大子数组和。分析:使用蛮力枚举解法,对具有n个元素的数组进行两次遍历,求取任意两个位置之间的数组的和,并记录,取最大值和最大值所在的索引为结果。此算法较为容易实现,但时间复杂度较高。参考汉诺塔的实现过程,若考虑将问题分解为小的问题,将问题规模缩小,分解过程如下:52首先找到数组的中间位置mid,然后考虑求解两个子数组A[low,mid]和A[mid+1,high]。那么A[low,high]的任何连续子数组A[i,j]所处的位置必然就是下列三种情况之一:① 完全位于子数组A[low,mid]中,因此low≤i≤j≤mid,最大子数组和记为S1;② 完全位于子数组A[mid+1,high]中,因此mid<i≤j≤high,最大子数组和记为S2;③ 跨越了中点,因此low≤i≤mid<j≤high,最大子数组和记为S3,分为左右两部分,S3=left+right,其中left是以A[mid]为结
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026年大竹县带编教师招聘笔试备考试题及答案解析
- 2026年惠东县带编教师招聘考试备考试题及答案解析
- 2026年新龙县带编教师招聘笔试备考试题及答案解析
- 2026年蓝田县带编教师招聘笔试备考试题及答案解析
- 2026年忠县带编教师招聘考试备考题库及答案解析
- 2026年平阳县带编教师招聘考试备考试题及答案解析
- 2026年峡江县带编教师招聘考试参考题库及答案解析
- 2026年会宁县带编教师招聘笔试备考试题及答案解析
- 2026年乐业县带编教师招聘考试模拟试题及答案解析
- 2026年宜丰县带编教师招聘笔试参考题库及答案解析
- 2026年菏泽市定陶区人民医院公开招聘合同制护理人员(16人)笔试备考题库及答案详解
- 2026 年师德师风教育:坚守廉洁从教树立幼教良好风尚课件
- 2026 年秋季高二开学第一课高中生家庭劳动实践主题班会
- 国资企业招聘笔试题库(全题型含答案解析)
- 2026-2030中国医疗仿真产品行业市场发展趋势与前景展望战略分析研究报告
- 2026年医院病案室招聘考试试题及答案
- 【江苏考区】2026年4月初级注册安全工程师《法律法规》考试真题
- 综合类专职安全员c3证考试题库及答案
- 肺康复知情同意书
- 【低空经济】无人机智能起降机柜设计方案
- 2026学年九年级化学上册第一单元核心考点第一次月考含答案及解析
评论
0/150
提交评论