11chap8函数讲稿(1[1]23)_第1页
11chap8函数讲稿(1[1]23)_第2页
11chap8函数讲稿(1[1]23)_第3页
11chap8函数讲稿(1[1]23)_第4页
11chap8函数讲稿(1[1]23)_第5页
已阅读5页,还剩65页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、Chap8 函数主要内容:1、函数的定义2、函数的调用(包括嵌套调用和递归调用)3、局部变量和全局变量4、变量的存储类别 5、综合题目重点:1)如何编写函数 2)如何调用函数(包括库函数和自定义函数) 第8章 函数8.1 概述模块化程序设计v基本思想:将一个大的程序按功能分割成一些小模块, (即函数也可以说是完成某些特定功能的代码块)。v函数的优点、特点:l各模块相对独立、功能单一、结构清晰、接口简单l易于维护和功能扩充l缩短开发周期(实现“编写一次,多次调用”,避免在不同的程序中重复编写相同的函数。)l避免程序开发的重复劳动v开发方法: 自上向下,逐步分解,分而治之8.2 函数的定义一般格式

2、合法标识符函数返回值类型缺省int型无返回值void函数体函数类型 函数名(形参类型说明表)说明部分语句部分现代常用形式:例 有参函数(现代风格) int max(int x,int y) int z; z=xy?x:y; return(z); 例 有参函数(现代风格) int max(int x, y) int z; z=xy?x:y; return(z); 例 空函数 dummy( ) 函数体为空例 无参函数void printstar( ) printf(“*n”); 或void printstar(void ) printf(“*n”); 形参类型说明表:类型名类型名 形式参数形式参数

3、1,类型名,类型名 形式参数形式参数2,) 空函数:空函数: 函数类型函数类型 函数名函数名( )( ) 调用此函数时,什么也不做。只是表明这里要 调用一个函数,而现在这个函数的功能还没实现。空函数在程序设计中常常用到的:空函数在程序设计中常常用到的:1 1)预留函数,便于以后扩充程序功能。)预留函数,便于以后扩充程序功能。2 2)便于程序的模块化设计和调试:)便于程序的模块化设计和调试:程序设计中往往根据需要确程序设计中往往根据需要确定若干模块,分别由一些函数来实现。一个大系统,需要编写很多用户函数,而这些函数不可能定若干模块,分别由一些函数来实现。一个大系统,需要编写很多用户函数,而这些函

4、数不可能 也没有必要同步完成,通常从一些基本模块开始,编写一个调试也没有必要同步完成,通常从一些基本模块开始,编写一个调试一个,对于没有编写一个,对于没有编写 的函数就需要用空函数代替。从而也有利于集体创作。的函数就需要用空函数代替。从而也有利于集体创作。注意良好的程序设计习惯良好的程序设计习惯:为了使程序具有良好的可读性并减少出错,凡不要求返返回值回值的函数都应定义为空类型;即使函数类型为整型,也不使用系统的缺省处理。不能嵌套定义函数!return8.3 函数的返回值返回语句v形式: return(表达式); 或 return 表达式; 或 return;v功能:使程序控制从被调用函数返回到

5、调用函数中,同时把返值带给调用函数v说明:l函数中可有多个return语句,但是只能返回一个确定的值。l若无return语句,遇时,自动返回调用函数l若函数类型与return语句中表达式值的类型不一致,按前者为准,自动转换-函数调用转换lvoid型函数例 无返回值函数 void swap(int x,int y ) int temp; temp=x; x=y; y=temp; 用8.4 函数的调用 重点重点1、如何调用一个函数、如何调用一个函数2、对被调函数的声明、对被调函数的声明3、主调函数和被调函数之间如何进行数据传递主调函数和被调函数之间如何进行数据传递调用形式 函数名(实参表);说明:

6、l实参与形参个数相等,类型一致,按顺序一一对应l实参表求值顺序,因系统而定(Turbo C 自右向左)对被调函数的声明对被调函数的声明v对被调用函数要求:l必须是已存在的函数l库函数: #include l用户自定义函数: 函数类型说明v函数说明l一般形式: 函数类型 函数名(形参类型 形参名,. ); 或 函数类型 函数名();(不常用)l作用:告诉编译系统函数类型、参数个数及类型,以便检验l函数说明位置:程序的数据说明部分(函数内或外)l下列情况下,可不作函数说明u若函数返值是char或int型,系统自动按int型处理u被调用函数定义出现在主调函数之前例 函数说明举例void main()

7、 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=xy?x:y; return(z);int型函数可不作函数说明float add(float x, float y) float z; z=x+y; return(z);void main() float a,b,c; scanf(%f,%f,&a,&b); c=add(a,b); printf(sum is %f,c);被调函数出现在主调函数之前,不必函

8、数说明void main() float add(float x,float y); /*function declaration*/ 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);float add();8.5 函数参数及其传递方式形参与实参v形式参数:定义函数时函数名后面括号中的变量名v实际参数:调用函数时函数名后面括号中的表达式c=max(a,b);(void main 函数)(ma

9、x 函数)max(int x, int y) int z; z=xy?x:y; return(z); 例 比较两个数并输出大者void main() int a,b,c; scanf(%d,%d,&a,&b); c=max(a,b); printf(Max is %d,c);max(int x, int y) int z; z=xy?x:y; return(z);形参实参v说明:l实参必须有确定的值l形参必须指定类型l形参与实参类型一致,个数相同l形参在函数被调用前不占内存;函数调用时为形参分配内存;调用结束,内存释放8.5 函数参数及其传递方式形参与实参v形式参数:定义函数时

10、函数名后面括号中的变量,此时的参数无具体的值,仅仅表示参数的类型、个数、以及在函数体内对其如何处理。v实际参数:调用函数时函数名后面括号中的表达式 其作用是:该函数被调用时用来接收实参的值.例 计算x的立方float cube(float x) return(x*x*x);void main() float a, product; printf(Please input value of a:); scanf(%f,&a); product=cube(a); printf(”Cube of %.4f is %.4fn,a,product);xaproduct1.21.21.828参数传

11、递方式v值传递方式l方式:函数调用时,为形参分配单元,并将实参的值复制到形参中;调用结束,形参单元被释放,实参单元仍保留并维持原值l特点:u形参与实参占用不同的内存单元u单向传递811x:y:调用前:调用结束:811x:y:写出程序的运行结果:#include void main() int x=8,y=11; void swap(int a,int b); printf(x=%d,ty=%dn,x,y); printf(swapped:n); swap(x,y); printf(x=%d,ty=%dn,x,y);void swap(int a,int b) int temp; temp=a;

12、 a=b; b=temp;调用:811a:b:811x:y:swap:811x:y:118a:b:tempv地址传递l方式:函数调用时,将数据的存储地址作为参数传递给形参l特点:u形参与实参占用同样的存储单元u“双向”传递u实参和形参必须是地址常量或变量如何定义一个函数如何定义一个函数如何定义一个函数第一步:参数分析函数需要的参数,包括参数的个数以及每个参数的类型分析函数需要的参数,包括参数的个数以及每个参数的类型 第二步:函数返回值函数返回值若无返回值为若无返回值为 void。 第三步:编写函数体编写函数体例如: 编写一个函数求求n!并调用并调用 要处理的数据是要处理的数据是n,因此必须有一

13、个参数因此必须有一个参数n,类型为类型为 int。返回值为返回值为long 型。即型。即 long fact( int n) 求求n!long int fact(int n)/*定义函数*/ long int p=1; while (n) p*=n-; return(p);void main()/*调用函数*/ int n; printf(input a n:n); scanf(%d,&n); printf(=%ld,fact(n); getch(); 作业 例例: 计算两个整数的最小公倍数计算两个整数的最小公倍数 void main()int m, n , min; int min_

14、multiple( int x, int y ); /*函数声明函数声明*/ printf(n input m,n:); scanf(%d%d,&m,&n); min=min_multiple(m,n); /*函数调用函数调用*/ printf(n bei shu:%d, min);int min_multiple(int x,int y) /*函数定义函数定义*/ int i; i=1; while(x*i%y!=0) i+; return(x*i);嵌套调用#include long sum(int a, int b); long factorial(int n);void

15、 main() int n1,n2; long a; scanf(%d,%d,&n1,&n2); a=sum(n1,n2); printf(a=%1d,a); long sum(int a,int b) long c1,c2; c1=factorial(a); c2=factorial(b); return(c1+c2); long factorial(int n) long rtn=1; int i; for(i=1;i=n;i+) rtn*=i; return(rtn); long sum(int a, int b);long factorial(int n);文件包含编译

16、预处理命令函数类型说明函数定义函数调用函数调用函数返回值形参实参8.6 函数的嵌套与递归调用嵌套调用C规定:函数定义不可嵌套,但可以嵌套调用函数void main( )调用函数a结束a函数b函数调用函数b例 求三个数中最大数和最小数的差值#include int dif(int x,int y,int z); int max(int x,int y,int z); int min(int x,int y,int z);void main() int a,b,c,d; printf(“input a,b,cn”); scanf(%d%d%d,&a,&b,&c); d=di

17、f(a,b,c); printf(Max-Min=%dn,d); int dif(int x,int y,int z) return max(x,y,z)-min(x,y,z); int max(int x,int y,int z) int r; r=xy?x:y; return(rz?r:z); int min(int x,int y,int z) int r; r=xy?x:y; return(r1)-规律 f(1)=1 (n=0,1)-递归结束条件例 求n的阶乘) 1()!1() 1 , 0(1!nnnnn#include float fac(int n) int f; if(n0) p

18、rintf(n=6) even(a); /*函数调用语句函数调用语句*/ else printf(The %d isnt even numbern,a); void even(int x) /*函数定义函数定义*/ int i; for(i=2;i=x/2;i+) if(isprime(i) if(isprime(x-i)printf(%d=%d+%dn,x,i,x-i); return ;int isprime(int a) /*函数定义函数定义*/ int i; for(i=2; ibi, ai=bi,aik,认为数组ab 若nk,认为数组ab 若n=k,认为数组a=b#include v

19、oid main() int a10,b10,i,n=0,m=0,k=0; printf(Enter array a:n); for(i=0;i10;i+)scanf(%d,&ai); printf(Enter array b:n); for(i=0;i10;i+)scanf(%d,&bi); for(i=0;iy) flag=1; else if(xy) flag=-1; else flag=0; return(flag);v参数传递分类:值、地址v地址传递l方式:函数调用时,将数据的存储地址作为参数传递给形参l特点:u形参与实参占用同样的存储单元u“双向”传递u实参和形参必

20、须是地址常量或变量数组名作函数参数v地址传递v在主调函数与被调函数分别定义数组,且类型应一致v形参数组大小(多维数组第一维)可不指定v形参数组名是地址变量例 求学生的平均成绩 #include float average(int stu10, int n); void void main() int score10, i; float av; printf(Input 10 scores:n); for( i=0; i10; i+ ) scanf(%d, &scorei); av=average(score,10); printf(Average is:%.2f, av); float

21、 average(int stu10, int n) int i; float av,total=0; for( i=0; in; i+ ) total += stui; av = total/n; return av; 实参用数组名形参用数组定义, int stu .2109score562312.88stu比较例 数组元素与 数组名 作函数参数比较12a调用前a0a112a调用a0a112xy21xy交换12a返回#include void swap2(int x,int y) int z; z=x; x=y; y=z;void main() int a2=1,2; swap2(a0,a1

22、); printf(a0=%dna1=%dn,a0,a1);值传递12a调用前12ax调用21ax交换21a返回#include void swap2(int x) int z; z=x0; x0=x1; x1=z;void main() int a2=1,2; swap2(a); printf(a0=%dna1=%dn,a0,a1);地址传递例 数组元素与 数组名 作函数参数比较举例例:编写函数实现:用冒泡法对例:编写函数实现:用冒泡法对n个整数升序排序。并个整数升序排序。并编写主函数实现数据的输入输出编写主函数实现数据的输入输出。分析:主程序的算法主程序的算法:S1:输入一批数据(个数为N

23、),存入一维数组a。 S2:调用函数sort(),对一维数组中的数据按从小到大的顺序排序。 S3:输出数组a中的各元素。函数函数sort()的编写的编写:首先,确定函数的类型:void;参数:一维数组的首地址,数据的个数,共2个;然后编写函数体,实现排序。重点:分析参数的传递,比较传值与传地址的区别,各有何用处?(图示:形参数组与实参数组的结合方式)wordword例 数组排序-简单选择排序void sort(int array,int n) int i,j,k,t; for(i=0;in-1;i+) k=i; for(j=i+1;jn;j+) if(arrayjarrayk) k=j; if

24、(k!=i) t=arrayi; arrayi=arrayk; arrayk=t; void main() int a10,i; printf(“input 10 numbers”); for(i=0;i10;i+)scanf(%d,&ai); sort(a,10); for(i=0;i10;i+) printf(%d ,ai); printf(n);0123456889a4968583299928138688arraykjjjkjkjjjjj949i=0例 数组排序-简单选择排序void sort(int array,int n) int i,j,k,t; for(i=0;in-1;

25、i+) k=i; for(j=i+1;jn;j+) if(arrayjarrayk) k=j; if(k!=i) t=arrayi; arrayi=arrayk; arrayk=t; void main() int a10,i; printf(“input 10 numbers”); for(i=0;i10;i+)scanf(%d,&ai); sort(a,10); for(i=0;i10;i+) printf(%d ,ai); printf(n);kjjkjkjjjjj0123456889a4968583299928138688array949kk1368i=10123456889a

26、9132832495868868899arrayi=8例 数组元素升序排序-简单选择排序void sort(int array,int n) int i,j,k,t; for(i=0;in-1;i+) k=i; for(j=i+1;jn;j+) if(arrayjarrayk) k=j; if(k!=i) t=arrayi; arrayi=arrayk; arrayk=t; void main() int a10,i; printf(“input 10 numbers”); for(i=0;i10;i+)scanf(%d,&ai); sort(a,10); for(i=0;i10;i+

27、) printf(%d ,ai); printf(n);数组数组a与数组与数组array实际上是一实际上是一个数组。个数组。array 的长度无意义,的长度无意义,因此可以不说明。因此可以不说明。比较两种参数传递方式传值调用:单向数据传递,对形参的改变不影响实参的值,且只能通过return语句返回最多一个值传地址调用:实参传给形参的是数据的地址,所达到的目的是:形参与实参共用同一片存储单元,对形参的改变实际上是对实参的改变,从而实现主、被调函数之间的多个数据传递。变量分类例 求二维数组中最大元素值1 3 5 82 4 6 815 18 34 12ijmax=11 3 5 82 4 6 815

28、18 34 12ijmax=31 3 5 82 4 6 815 18 34 12ijmax=5j1 3 5 82 4 6 815 18 34 12imax=8j1 3 5 82 4 6 815 18 34 12imax=8j1 3 5 82 4 6 815 18 34 12imax=34int max_value(int array34) int i,j,k,max; max=array00; for(i=0;i3;i+) for(j=0;jmax) max=arrayij; return(max);void main() int a34=1,3,5,8, 2,4,6,8,15,18,34,1

29、2; printf(max value is %dn,max_value(a);多维形参数组第一维维数可省略,第二维必须相同 int array4变量分类8.8 变量的分类概述v变量是对程序中数据的存储空间的抽象内存.void main() int x; x=10; printf(“%d”,x);编译或函数调用时为其分配内存单元1020002001程序中使用变量名对内存操作v变量的属性l数据类型:变量所持有的数据的性质(操作属性)l存储属性u存储器类型:寄存器、静态存储区、动态存储区u生存期:变量在某一时刻存在-静态变量与动态变量u作用域:变量在某区域内有效-局部变量与全局变量v变量的存储类型

30、lauto -自动型lregister-寄存器型lstatic -静态型lextern -外部型v变量定义格式: 存储类型 数据类型 变量表;如: int sum; auto int a,b,c; register int i; static float x,y;作用域自动的(auto)变量函数的形参和在函数中定义的变量(通常省略存储类别,)即隐含指定为自动变量。前面17章中的变量均属自动变量。自动变量在需要时系统给他门分配存储空间,在函数调用结束时自动释放这些存储空间。例auto int a=2,b=3; 与int a=2,b=3;等价。静态的(static)1、静态局部变量:作用域为本函数

31、内部存储类别为静态存储类,因此其生存期与该函数所在程序运行期间相同。即当函数调用结束时能保留原值,在下一次调用该函数时该变量的值是上一次函数调用结束时的值,直至程序运行结束。void main() void increment(void); increment(); increment(); increment();void increment(void) int x=0; x+; printf(“%dn”,x);例 局部静态变量值具有可继承性运行结果:1 1 1void main() void increment(void); increment(); increment(); increm

32、ent();void increment(void) static int x=0; x+; printf(“%dn”,x);运行结果:1 2 3Register 变量register int k; 则给变量k分配的空间为某个寄存器。优点:速度快。只有局部变量和形参可以定义为register变量。因为机器的寄存器数量有限,因此该类型不常用。外部的(extern)变量用extern声明外部变量,是为了扩展外部变量的作用域。因外部变量不常用,因此extern也很少使用。必须使用外部变量时,一般建议使用静态全局变量。即在函数体外定义变量时存储类别为:static 如 static int a=2;

33、f( ) 变量 a的作用范围仅限于本源程序文件内。其它程序中即使用extern int a;声明也不能引用a。综合题1编程实现小学生算术练习系统:主菜单包括5项(加法、减法、乘法、除法、退出),前四项中每一项又包括子菜单(一级、二级、三级、返回4项),其中一级实现10以内的运算,二级实现50以内的整数运算,三级实现100以内的整数运算;进入某一级后,反复练习(由机器产生两个随机数random(),用户输入运算结果,输出正确或错误)待结束时给出本级题目中计算正确的百分比。要求每个功能分别用函数实现。作业综合题2自动阅卷程序:设单选题20个(2分/题),多选题20个(每题4个供选答案,3分/题,且

34、只要与答案不一致即错)。编写函数实现:阅单选题,阅多选题,阅一个人的答题;编写主函数实现批阅N个人的答题卡(正确答案在主程序中输入)。分析:void main(): 1)输入正确答案,分别存入一维数组dd,二维数组ss; 2) 批阅N个人的答题(用循环),将成绩存入数组sc。3)输出每个人的最后成绩。person(): 函数类型为int; 参数两个:dd,ss; 函数体:1)输入某人的答案,分别存入dd1和ss1,2)分别调用函数single()和many()判别对错并计分,返回总成绩。single():函数类型int ,参数dd,dd1; 函数体:统计数组dd与dd1中相同元素的个数,乘2即

35、得单选题的成绩,返回该成绩。many():函数类型int ,参数ss,ss1; 函数体:统计数组ss与数组ss1中对应行元素相同的行数,乘3即得多选题的成绩,并返回。然后分析各函数的具体实现算法。程序1:分析程序中的传地址调用,嵌套调用时程序的执行过程。程序2:定义存放正确答案的数组为全局的,则dd,ss将不作为参数使用。(一般情况使用参数传递)#include stdio.h /*程序1*/#define N 400 /*num of person*/#define NUM 20 /*num of question*/void main() char ddNUM+1,ssNUM+15; in

36、t scN+1,i; printf(n enter right answer of single select:n); printf(n(format:press enter after finished inputing all of answers.n); for(i=1;i=NUM;i+) ddi=getchar(); getchar(); printf(n enter answer of multi select:n); printf(nformat:(press enter after inputing a question)n); for(i=1;i=NUM;i+) gets(ss

37、i); for(i=1;i=N;i+) sci=person(dd,ss); printf(n no: score: ); for(i=1;i=N;i+) printf(n %-6d%-6d,i,sci);int person(char dd,char ss5) char dd121,ss1315; int s,i; int signle(),many(); printf(n enter answer of single select:); for(i=1;i=NUM;i+) dd1i=getchar(); getchar(); printf(n enter answer of multi s

38、elect:); for(i=1;i=NUM;i+) gets(ss1i); s=single(dd,dd1)+many(ss,ss1); return(s);int single(char dd ,char dd1 ) int n=0,i; for(i=1;i=NUM;i+) if(ddi=dd1i) n+; return(2*n);int many(char ss 5,char ss1 5) int n=0,i; for(i=1;il外部变量说明: extern 数据类型 变量表;l若外部变量与局部变量同名,则外部变量被屏蔽特别注意:Y若局部与全局变量同名,则局中局优先Y全局变量在程序全部

39、执行过程中占用存储单元,不提倡使用Y应用:从函数返回多个返回值局部变量和全局变量小结局部变量:保证了函数之间的独立性。(常用)全局变量:增加了函数之间数据传递的通道,但降低了函数间的独立性,降低了程序的清晰性,因此副作用太大。除非特别需要时,一般不用。占用内存情况:局部变量仅当他所在的函数被调用时才存在,执行完该函数返回后,该变量不再存在全局变量在程序的全部执行过程中一直存在,直至程序执行完,才释放它所占的内存空间2、从生存期分:动态变量与静态变量v存储方式l静态存储:程序运行期间分配固定存储空间l动态存储:程序运行期间根据需要动态分配存储空间v内存用户区程序区静态存储区动态存储区全局变量、局部静态变量形参变量局部动态变量(auto register)函数调用现场保护和返回地址等v生存期l静态变量:从程序开始执行到程序结束l动态变量:从包含该变量定义的函数开始执行至函数执行结束 静态变量:分配固定空间,程序整个运行期间都存在。从程序开始执行到程序结。(编译时初始化;程序运行期间

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论