《图片形式的》PPT课件.ppt

上传人:牧羊曲112 文档编号:5484704 上传时间:2023-07-12 格式:PPT 页数:79 大小:650.50KB
返回 下载 相关 举报
《图片形式的》PPT课件.ppt_第1页
第1页 / 共79页
《图片形式的》PPT课件.ppt_第2页
第2页 / 共79页
《图片形式的》PPT课件.ppt_第3页
第3页 / 共79页
《图片形式的》PPT课件.ppt_第4页
第4页 / 共79页
《图片形式的》PPT课件.ppt_第5页
第5页 / 共79页
点击查看更多>>
资源描述

《《图片形式的》PPT课件.ppt》由会员分享,可在线阅读,更多相关《《图片形式的》PPT课件.ppt(79页珍藏版)》请在三一办公上搜索。

1、,第7章 函数,本章内容包括函数的基本概念和函数的定义方法;函数的调用、函数参数和函数的值;函数的嵌套调用;函数的递归调用;数组做函数参数;变量的类型:全局变量和局部变量;静态存储变量和动态存储变量;函数的分类:外部函数和内部函数。,1.如果有两个同学参加学生会主席的竞选,现已统计出两个人的总得分,怎么确定谁当选?(用函数来实现),提出问题,相关知识点,7.1 函数的定义、函数参数和函数的值7.2 函数的调用,7.1.1 C语言对函数的规定,1、一个源程序文件由一个或多个函数组成2、一个c程序由一个或多个源程序文件组成3、c程序的执行从main函数开始到main()函数结束4、所有函数都是平行

2、的,函数不能嵌套定义5、函数按使用角度分:标准函数、自定义函数,按形式分:无参函数、有参函数,7.1.2 函数定义的一般形式,1、无参函数的定义形式 类型说明符 函数名()声明部分 语句,3、可以有“空函数”类型说明符 函数名(),2、有参函数的定义形式类型说明符 函数名(形参列表)声明部分 语句,现在我们试着写出问题1的函数。(1)两个数求最大值,定义两个形参x,y,从x,y中找到最大者,最大者的类型即函数类型。可得函数的首部:int max(int x,int y)(2)写出函数体,实现两个数求最大值int max(int x,int y)int z;z=xy?x:y;/*z为x,y中得最

3、大者*/return(z);注意:return(z)的作用是将z的值作为函数值带回主调函数中。即将最大值带回,说明:(1)形参列表样式:int x,int y,注意:每个形参都有类型;(2)函数类型原则上要求与return后表达式类型一致,如不一致,表达式类型强制转换成函数的类型;如果函数的确不需要返回值,设为void型;(3)return语句作用,一是:带返回值到函数调用处;二是:将流程返回函数调用处;如果该函数没有返回值,可以省略return,最后的 也具有将流程返回调用处的功能。(4)如何确定一个函数是否需要返回值?想一想,我们真的将问题1完全解决了吗?,7.2 函数的调用,1、函数调用

4、的一般形式:函数名(实参列表);回顾函数定义的一般形式:函数类型 函数名(形参列表),2、C程序的一般结构:main()语句 函数名(实参列表);/*函数调用*/语句 函数类型 函数名(形参列表)/*函数定义*/函数体 return语句,1.如果有两个同学参加学生会主席的竞选,现已统计出两个人的总得分,怎么确定谁当选?(用函数来实现),解决问题,例7.1求两个数的最大值。main()int a,b,c;a=12;b=34;c=max(a,b);/*函数调用*/printf(“max=%dn”,c);int max(int x,int y)/*函数定义*/int z;z=xy?x:y;retur

5、n(z);,分析例7.1的执行过程,a,b,12,34,x,y,12,34,主函数开始执行,定义变量a,b,c,a,b赋初值,主函数执行下述语句时,c=max(a,b);传值给被调用函数 int max(int x,int y),被调用函数开始执行,定义变量z,z存放最大值,c,z,主函数执行下述语句 z=xy?x:y;,34,被调用函数执行下述语句时,return(z);带返回值z给主函数 c=max(a,b);,34,注意 被调函数执行完,主函数继续执行,输出最大值。printf(“max=%dn”,c);,2.设某班50人,写一程序统计某一单科成绩各分数段的分布人数,每人的成绩随机输入,

6、并要求按下面格式输出统计结果(“*”表示实际分布人数)。059*6084*85100*,问题的深化,算法思想:(1)定义一个输出n个“*”的函数。(2)在main函数中统计各分数段的人数,分别用n1,n2,n3来存放(3)在函数调用时,n1作实参,传给形参n,输出059的分布人数,n2作实参,传给形参n,输出6084的分布人数,n3作实参,传给形参n,输出85100的分布人数。,例7.2 成绩分布情况(为简化问题,我们输入10个成绩)#include void star(int n)int i;for(i=0;in;i+)printf(*);printf(n);,main()int i,j,n

7、1,n2,n3,score;i=1;n1=n2=n3=0;while(i=0,1.猜年龄。5个小朋友排着队作游戏,第1个小朋友10岁,其余的年龄一个比一个大2岁,第5个小朋友的年龄?,提出问题,相关知识点,7.3 函数的嵌套调用7.4 函数的递归调用,7.3 函数的嵌套调用,嵌套调用的定义:C语言的函数调用可以嵌套,即在调用一个函数的过程中,可以再调用另一个函数;,例如:int f1(int n)main()int y;int a;if(n5)y=f2(n);scanf(“%d”,7.4 函数的递归调用,1、什么是递归调用 递归就是某一事物直接或间接地由自己组成。故在调用一个函数的过程中,又出

8、现直接或间接地调用 该函数本身,称为函数的递归调用;2、递归的方式:直接递归、间接递归,1.猜年龄。5个小朋友排着队作游戏,第1个小朋友10岁,其余的年龄一个比一个大2岁,第5个小朋友的年龄?,解决问题,算法思想:设age(n)是求第n个人的年龄,那么,根据问题1的题义,我们可知:age(5)=age(4)+2age(4)=age(3)+2age(3)=age(2)+2age(2)=age(1)+2age(1)=10,可以用数学公式表述如下:10(n=1)age(n)=age(n-1)+2(n1),下面用图表示求第5个人年龄的过程。,例7.3问题1的源代码:age(int n)/*求年龄的递归

9、函数*/int c;/*c用作存放函数的返回值的变量*/if(n=1)c=10;else c=age(n-1)+2;return c;main()printf(“age(5)%d”,age(5);,采用递归方法求1+2+3+n的和.该问题的递归公式:1(n=1)sum(n)=sum(n-1)+n(n1)当n为1时,函数值为1是递归出口.,采用递归方法求n!.该问题的递归公式:1(n=1或n=0)Fia(n)=Fia(n-1)*n(n1)当n为1或0时,函数值为1是递归出口.,2.计算机协会在举办“数学趣味游戏”,老师对婷婷说,我给你一个整数,若它是偶数,将它除以2;若它是奇数,将它乘以3加1。

10、得到的结果再继续判断,是偶数,除以2;是奇数,乘以3加1,最后,看看这个数变成几?你会发现,不管我给你的是什么数,最终,它会变成1。现在,你编程验证以下。,问题的深化,算法思想:这是“角谷猜想”的问题。(1)输入一个整数(2)如果是,转(4)结束。否则转(3)(3)如果是偶数,;否则;转(2)(4)输出从中可以看出是递归出口,用递归函数实现第(3)步,例7.4 角谷猜想main()int n;printf(input a number:);scanf(%d,3.相传古代印度布拉玛神庙中有一个僧人,他每天不分白天黑夜,不停地移动那些圆盘,据说,当所有64个圆盘全部从一根杆上移到另一根杆上的那一天

11、就是世界的末日。这就是著名的汉诺塔(Hanoi)问题。如图:一次只能移动一个盘,且不允许大盘放在小盘的上面。,自主学习,算法思想:怎样编写这种程序?思路上还是先从最简单的情况分析起,搬一搬看,慢慢理出思路。1、在A柱上只有一只盘子,假定盘号为1,这时只需将该盘从A搬至C,一次完成,记为 move 1 from A to C,2、在A柱上有二只盘子,1为小盘,2为大盘。第(1)步将1号盘从A移至B,这是为了让2号盘能移动;第(2)步将2号盘从A移至C;第(3)步再将1号盘从B移至C;这三步记为:move 1 from A to B;move 2 from A to C;move 3 form B

12、 to C;,3、在A柱上有3只盘子,从小到大分别为1号,2号,3号第(1)步将1号盘和2号盘视为一个整体;先将二者作为整体从A移至B,给3号盘创造能够一次移至C的机会。这一步记为move(2,A,C,B);意思是将上面的2只盘子作为整体从A借助C移至B。第(2)步将3号盘从A移至C,一次到位。记为move 3 from A to C;第(3)步处于B上的作为一个整体的2只盘子,再移至C。这一步记为move(2,B,A,C);意思是将2只盘子作为整体从B借助A移至C。,4、从题目的约束条件看,大盘上可以随便摞小盘,相反则不允许。在将1号和2号盘当整体从A移至B的过程中move(2,A,C,B)

13、实际上是分解为以下三步第(1).1步:move 1 form A to C;第(1).2步:move 2 form A to B;第(1).3步:move 1 form C to B;经过以上步骤,将1号和2号盘作为整体从A移至B,为3号盘从A移至C创造了条件。同样,3号盘一旦到了C,就要考虑如何实现将1号和2号盘当整体从B移至C的过程了。实际上move(2,B,A,C)也要分解为三步:第(3).1步:move 1 form B to A;第(3).2步:move 2 form B to C;第(3).3步:move 1 form A to C;,5、看move(2,A,C,B)是说要将2只盼

14、自从A搬至B,但没有C是不行的,因为第(1).1步就要将1盘从A移到C,给2盘创造条件从A移至B,然后再把1盘从C移至B。看到这里就能明白借助C的含义了。因此,在构思搬移过程的参量时,要把3个柱子都用上。,6、定义搬移函数move(n,A,B,C),物理意义是将n只盘子从A经B搬到Cmove(n,A,B,C)分解为3步(1)move(n-1,A,C,B)理解为将上面的n-1只盘子作为一个整体从A经C移至B;(2)输出n:A to C,理解将n号盘从A移至C,是直接可解结点;(3)move(n-1,B,A,C)理解为将上面的n-1只盘子作为一个整体从B经A移至C。这里显然是一种递归定义,当解mo

15、ve(n-1,A,C,B)时又可想到,将其分解为3步:第1步:将上面的n-2只盘子作为一个整体从A经B到C,move(n-2,A,B,C);第2步:第n-1号盘子从A直接移至B,即n-1:A to B;第3步:再将上面的n-2只盘子作为一个整体从C经A移至B,move(n-2,C,A,B);,源代码:,int step=1;/*整型全局变量,预置1,步数*/void move(int,char,char,char);/*声明要用到的被调用函数*/void main()int n;/*整型变量,n为盘数,*/printf(请输入盘数n=);scanf(%d,/*调用函数 move(n,a,b,c

16、)*/,/*以下函数是被主程序调用的函数*/void move(int m,char p,char q,char r)/*自定义函数*/if(m=1)/*如果m为1,则为直接可解结点,*/printf(%d move 1#from%c to%cn,step,p,r);/*直接可解结点,输出移盘信息*/step=step+1;/*步数加1*/else/*如果不为1,则要调用move(m-1)*/move(m-1,p,r,q);/*递归调用move(m-1)*/printf(%d move%d#from%c to%cn,step,m,p,r);/*直接可解结点,输出移盘信息*/step=step+

17、1;/*步数加1*/move(m-1,q,p,r);/*递归调用move(m-1)*/,本讲小结:,1、什么是嵌套调用?2、什么是递归调用?递归出口、递归过程。,1.在体育课上,20个学生正在测试100米,老师把学生成绩一一记录下来。现在将学生由快到慢排序,你能帮忙排一排?(用函数实现),提出问题,相关知识点,7.5 数组作为函数参数,7.5 数组作为函数参数,一、数组元素作函数实参数组元素实际上就是该类型的一简单变量,如:有一整型数组a定义:int a10;则其中的数组元素a1就是一 个整型变量,所以,数组元素作为函数的实参,与用变量做实参一样,是单向传递,即“传值调用”。,例如:void

18、swap(int x,int y)int t;t=x;x=y;y=t;printf(“%d,%dn”,x,y);main()int a=3,5,2;/*数组a定义初始化*/printf(“%d%dn”,a1,a2);swap(a1,a2);/*调用swap函数*/printf(“%d%d”,a1,a2);,二、一维数组名作函数实参,数组名代表数组的首地址,所以,在函数调用时,把数组名作为函数实参传递,实质上就是把该数组的首地址传给了形参,称为“传址调用”。什么是“传值”?什么是“传址”?所传数据类型不同:,1.在体育课上,20个学生正在测试100米,老师把学生成绩一一记录下来。现在将学生由快到

19、慢排序,你能帮忙排一排?(用函数实现),解决问题,算法思想:主调函数main:程序的入口,包含主要的操作将20个学生的成绩用数组a存放,有20个元素;输出排序前的成绩,即:输出数组a 的20个元素值;调用函数来实现学生成绩的排序,即:对数组排序;输出排序后的成绩,即:调用返回后,输出数组a 的20个元素值;被调用函数sort:用起泡法对数组元素排序。,源代码:#includevoid sort(float b,int n)int i,j;float t;for(j=1;jai+1)/*aiai+1为真*/t=ai;ai=ai+1;ai+1=t;/*将ai与ai+1对换*/main()float

20、 a11;/*将10个数给a1到a10,故定义数组长度为11*/int i;printf(“input 10 numbers:n”);/*输入10个数*/for(i=1;i11;i+)scanf(“%f”,说明:(1)数组名代表数组的首地址;(2)数组名作函数实参,传递的是数组的首地址称为传址调用;(3)“传值”、“传址”只是传递的数据类型不同(传值-一般的数值,传址-地址)。(4)不管“传值”、还是“传址”,C语言都是单向传递数据的,一定是实参传递给形参,反过来不行。也就是说C语言中函数参数传递的 两种方式本质相同“单向传递”;(5)传址调用机制:,分析:实参a数组的地址传给形参b数组,so

21、rt函数对形参b数组用起泡法排序,其实实质就是对实参数组a排序,达到目的。结论:传址调用,实参地址传递给形参,形参中的改变就是实参中的改变,可以理解成双向的:实参的地址值 形参的地址值 即 实参的数值 形参的数值,三、二维数组名作函数参数,作用:与一维数组名作函数参数相同。说明:(1)在被调用函数中,形参数组定义时可以指定每一维的大小,也可以省略第一维的大小说明,但是不能把第二维的大小说明省略,更不能只指定第一维而省略第二维。(2)实参数组可以大于形参数组。这时形参数组只取实参数组的一部分,其余部分不起作用。,2.给定某年某月某日,将其转换成这一年的第几天并输出。,问题的深化,算法思想:若给定

22、的月是I,则将1、2、3、I-1月的各月天数累加,再加上指定的日。但对于闰年,二月的天数29天,因此还要判定给定的年是否为闰年。为实现这一算法,需设置一张每月天数列表,给出每个月的天数,考虑闰年/平年的情况,此表可设置成一个2行3列的二维数组,其中第一行对应的每列(设112列有效)元素是平年个月的天数,第二行对应的是闰年每月的天数。,源代码:#includeint day_of_year(int day113,int year,int month,int day)int i,j;i=(year%4=0,7.6 局部变量和全局变量,变量的分类:变量从数据类型的角度,可以分为整型、实型、字符型等。

23、变量从作用域(变量的有效范围,可见性)的角度可以分为局部变量和全局变量。变量定义的位置决定了变量的作用域。,7.7.1 局部变量,1、定义:是指定义在函数内部或程序块内的变量,局部 有效,也成为内部变量。2、作用域:为块(复合语句)作用域,即从定义点开始到所在块结束。,3、C语言中,在以下各位置定义的变量均属于局部变量。(1)函数体内定义的变量,在本函数范围内有效,作用域局限于函数体内。(2)在复合语句内定义的变量,在本复合语句范围内有效,作用域局限于复合语句内。(3)有参函数的形式参数也是局部变量,只在其所在的函数范围内有效。,double fun1(int x,int y)/*x,y,m,

24、n局部变量,在fun1函数内有效(作用域fun1函数)*/int m,n;.int fun2(char ch)/*ch,a,b局部变量,在fun2函数内有效(作用域fun2函数)*/int a,b;.main()int a,b;/*a,b局部变量,在main函数内有效(作用域main函数)*/.int x,y;/*x,y局部变量,在复合语句中有效(作用域复合语句)*/.,4、说明:(1)main中定义的变量也只在main中有效,而且,main也不能使用其它函数中定义的变量。(2)同名,不同作用域的变量是不同的变量。(3)在各个函数中的局部变量起作用的时刻是不同的。,例子1 不同函数中同名不同义

25、的变量f1(int n)int m;if(n100)m=n-10;else m=n+1;printf(“%dn”,m);main()int m;scanf(“%d”,假设输入80,试分析程序的执行情况,例子2 不同复合语句(程序段)中同名不同义的变量main()int x,y;x=10;y=20;printf(“%d,%dn”,x,y);int y=10;x=y+5;printf(“%d,%dn”,x,y);printf(“%d,%dn”,x,y);,7.6.2 全局变量,1、定义:是指定义在所有函数之外的变量,所有函数前、各个函数之间、所有函数后,也成为外部变量。int max;int f1

26、(int n)void f2()main(),int f1(int n)int max;void f2()main(),max的使用范围,2、作用域:从定义全局变量的位置起到本源程序结束为止。3、说明:(1)置全局变量的作用是为了增加函数间数据联系的渠道;例如:当有多个返回值需要带回时,可以使用全局变量。(2)使用全局变量时,一定要小心!因为:全局变量在程序的全部执行过程中都有效,一个函数的使用会影响到其他函数的使用。(3)在同一范围内,如果全局变量与局部变量同名,则局部变量优先于全局变量.,例如:int a=3,b=5;/*a、b为全局变量*/int max(int a,int b)/*a、

27、b为局部变量*/return ab?a:b;形参a、b作用范围 main()int a=8;/*a为局部变量*/局部变量a作用范围 printf(“%d”,max(a,b);分析:运行结果:,说明:局部变量a有效,全局变量a失效。,7.7 动态存储变量与静态存储变量,7.7.1 变量的存储类别1、变量的生存期(1)定义:指变量值存在的时间长短。(2)根据变量生存期的不同,可以将变量分为:动态存储变量和静态存储变量。变量的存储方式决定了变量的生存期。,2、变量的存储方式(1)动态存储方式:是指在程序运行期间根据需要动态分配存储空间的存储方式;即需要时给存储空间,不需要时就释放;如 形参;(2)静

28、态存储方式:是指在程序运行期间分配固定的存储空间的存储方式;如 全局变量;,3、变量的存储类别(1)定义:是指在内存中存储的方法。(2)根据变量的作用域和生存期不同,可以将变量分为以下四类存储类别:,局部变量的存储方式,1、auto:(1)默认存储类别,函数内、复合语句中定义的局部变量和形参 均是 auto型,属于局部变量的范畴auto int a,b=2;与int a,b=2;二者等价(2)自动变量是动态的。其所在的函数或复合语句执行时,系统动态为相应的自动变量分配存储单元,当自动变量所在的函数或复合语句执行结束后,自动变量失效,它所在的存储单元被系统释放,所以原来的自动变量的值不能保留下来

29、。,2、register:与auto类似,是C语言使用较少的一种局部变量的存储方式。该方式将局部变量存储在CPU的寄存器中,寄存器比内存操作要快很多,所以可以将一些需要反复操作的局部变量存放在寄存器中,也是动态的。注:CPU的寄存器数量有限,如果定义了过多的register变量,系统会自动将其中的部分改为auto型变量。,3、static:(1)被定义为static 类型的局部变量,具有固定的存储空间,即使调用结束,其存储空间也不被释放,是静态的;(2)被定义为static 类型的局部变量,是在编译时赋初值的,即只赋初值一次;以后每次调用函数时,不再重新赋初值而只是保留上次函数调用结束时的值;

30、(3)如在定义局部变量时不赋初值,则对static 类型的变量来说,编译时自动赋初值0(对数值型变量)或(空字符,对字符型变量);,例:#includeint f(int a)auto int b=0;/*自动,auto可省*/static int c=3;/*静态,值保留*/b+;c+;return(a+b+c);,main()int a=2,I;/*自动,默认auto*/for(I=0;I3;I+)printf(“%d”,f(a);,4、extern:可以扩大作用域.例如:int max(int x,int y)return xy?x:y;main()extern int a,b;prin

31、tf(“%d”,max(a,b);int a=13,b=-8;,全局变量的存储方式,1、全局变量全部是静态存储的。2、没有必要为说明全局变量是静态存储而使用关键词static。3、全局变量的extern声明及令人困惑的全局变量的static定义。,7.8 内部函数和外部函数,7.8.1 内部函数1、定义:只能被本源文件(模块)中的各个函数所调用,不能为其它模块中函数所调用的函数。2、格式:在定义内部函数时,在函数名和函数类型前面加static。即:static 类型标识符 函数明(形参表)如:static int max(int a,int b),3、说明:(1)内部函数又称为静态函数,其使用

32、范围仅限于定义它的模块(源文件)内。对于其它模块它是不可见的。(2)不同模块中的内部函数可以同名,它们的作用域不同-事实上根本就是不同的函数。(3)内部函数定义,static关键词不能省略。,7.8.2 外部函数,1、定义:能被任何源文件(模块)中的任何函数所调用的函数。2、格式:定义函数时,加extern说明。即:extern 类型标识符 函数明(形参表)如:extern int max(int a,int b)3、说明:,本讲小结,分程序作用域(复合语句作用域)局部变量 函数作用域 变量的作用域 文件作用域(模块作用域)全局变量 程序作用域 auto(动态)static(静态)文件作用域 局部变量的存储 register(动态)全局变量 扩大 static(静态)的存储 extern(静态)程序作用域 static(内部)函数的作用域 extern(外部),

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

当前位置:首页 > 生活休闲 > 在线阅读


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号