C语言程序设计函数市公开课金奖市赛课一等奖课件_第1页
C语言程序设计函数市公开课金奖市赛课一等奖课件_第2页
C语言程序设计函数市公开课金奖市赛课一等奖课件_第3页
C语言程序设计函数市公开课金奖市赛课一等奖课件_第4页
C语言程序设计函数市公开课金奖市赛课一等奖课件_第5页
已阅读5页,还剩59页未读 继续免费阅读

下载本文档

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

文档简介

第7章函数第1页模块化程序设计基本思想:将大程序按功效分割成一些小模块,特点:各模块相对独立、功效单一、结构清楚简单控制了程序设计复杂性每个模块简单,所以可靠性高防止程序开发重复劳动,缩短开发周期易于维护和功效扩充开发方法:自上向下,逐步分解,分而治之,是面向过程程序设计语言关键第7章函数7.1.1C程序结构第2页

C程序基本结构C程序源程序文件1源程序文件2源程序文件n…预编译命令函数1函数2…说明部分执行部分第3页可由一个或多个源程序文件组成;每个源程序文件又由若干函数组成;但整个程序有且仅有一个主函数;程序运行时从main函数开始执行,main函数可调用其它函数,最终一律返回到main函数结束运行。除main函数外,其它函数可相互调用;函数不可嵌套定义,含有全局性、平行性;函数分为有参加无参函数,有返回值和无返回值函数,主调和被调函数

C程序特点:第4页函数分类按照函数定义角度分为:1.标准库函数:是由系统定义地,也无须在程序中进行类型说明,要调用某个库函数,则要用预处理命令#include将该函数所在头文件包含到程序中。使用库函数应注意:1、函数功效2、函数参数数目和次序,及各参数意义和类型3、函数返回值意义和类型4、需要使用包含文件第5页当标准库函数中没有用户要用函数时,就必须自己设计了,设计函数标准是:1,函数不应处理太多功效,要保持函数小型化,功效单一化.

2,一个函数要保持自己独立性,如同一个黑匣子一样,有进有出.

3,在函数中多使用复合语句,使函数也含有结构化,而且能够提升执行效率和节约存放空间.

4,在主函数前,要罗列出全部使用自定义函数原型说明,这有利于在大型程序设计中追踪要调用函数设置是否正确.

5,在程序适当地方加入注释(用/*...*/包含语句)这便于程序阅读和调试.

6,采取层次书写程序格式,按程序不一样功效分层次.2.用户自定义函数第6页按照函数参数传递形式分为:无参函数有参函数按照函数返回值类型分为:有返回值无返回值按照函数使用范围分为:内部函数外部函数按函数定义形式和使用范围分类:第7页8.2函数定义------无参函数定义类型名函数名(){申明部分执行部分}说明:类型名为函数返回值类型,假如定义时未指定,系统默认为int型;无返回值函数类型名应为void。函数名须是正当标识符,不能与其它函数或变量重名第8页#include<stdio.h>voidprintstar(){printf("*************\n");}voidprint_message(){printf("Howareyou!\n");}main(){

printstar();print_message();printstar();}第9页类型标识符函数名(形参表列){申明部分执行部分}形参表列必须申明形参类型函数定义------有参函数定义形参类型说明表,普通格式为:数据类型1形参1,…,数据类型n形参n第10页#include<stdio.h>floataverage(floatx,floaty,floatz)

{floataver;aver=(x+y+z)/3;return(aver);}main(){floata,b,c,ave;a=6.5;b=4.2;c=25.3;

ave=average(a,b,c);

printf(“average=%f”,ave);}第11页void函数名(){}函数体能够没有,表示占个位置,实现功效以后补写。函数定义------空函数定义第12页/*求最大值*/voidmax(intx[]){/*求最大值*/}空函数应用main(){inta[10]={….};

/*求最大值*/intm_max=max(a);printf(“m_max=%d”,m_max);}第13页函数调用:

1、主调函数与被调函数main函数是整个程序执行入口程序执行是从main函数开始普通函数必须由main函数(或其它函数)调用才能执行。函数调用关系示意图第14页2、函数参数和函数值函数参数分为:实际参数和形式参数在函数定义函数首部,函数名后括号中说明变量,简称形参。形参个数能够有多个,多个形参之间用逗号隔开。形式参数:实际参数:函数被调用时,在调用处给出对应参数,简称实参,实参往往是含有明确值常量、变量或表示式等。第15页#include<stdio.h>floataverage(floatx,floaty,floatz)

{floataver;aver=(x+y+z)/3;return(aver);}main(){floata,b,c,ave;a=6.5;b=4.2;c=25.3;

ave=average(a,b,c);

printf(“average=%f”,ave);}形式参数(形参)实际参数(实参)第16页注意:1.形参在未出现函数调用时,他们并不占内存,只有发生函数调用时才会被分配空间,而且在该函数结束后,它所占全部内存也被释放;2.实参必须是含有确定值常量,变量或表示式;3.形参必须在定义时就申明其类型;6.实参加形参类型应相同或赋值兼容;7.C语言要求,实参加形参之间必须是单向值传递。4.实参个数和形参个数应该相等;5.实参加形参在次序上应该一一对应;参数结合问题:在函数调用时,将实参值传给对应形参第17页比如:编一程序,将主函数中两个变量值传递给swap函数中两个形参,交换两个形参值。#include<stdio.h>voidswap(intx,inty){intz;z=x;x=y;y=z; printf("\nx=%d,y=%d",x,y);}main(){inta=10,b=20;swap(a,b);printf("\na=%d,b=%d\n",a,b);}形式参数(形参)实际参数(实参)单向值传递第18页比如:编一程序,将主函数中两个变量值传递给swap函数中两个形参,交换两个形参值。#include<stdio.h>voidswap(intx,inty){intz;z=x;x=y;y=z; printf("\nx=%d,y=%d",x,y);}main(){inta=10,b=20;swap(a,b);printf("\na=%d,b=%d\n",a,b);}程序输出结果:x=20,y=10a=10,b=20mainswap20b10az10y20x101020交换失败第19页例计算x立方#include<stdio.h>floatcube(floatx){return(x*x*x);}main(){floata,product;printf("Pleaseinputvalueofa:");scanf("%f",&a);product=cube(a);printf(”Cubeof%.4fis%.4f\n",a,product);}xaproduct××××1.21.21.728第20页函数值即函数返回值,是经过函数中return语句取得.return语句普通形式:return(表示式);return表示式;执行过程:执行return语句后,假如该表示式类型与函数首部中定义函数类型一致,则直接将结果返回主调函数;不然,系统自动将结果类型转换成定义函数类型。第21页无返回值函数

假如被调用函数中没有return语句,函数带回是一个不确定值。为了明确表示“不带回值”,能够用“void”定义“无类型”(或称“空类型”)。这么,系统就确保不使函数带回任何值,即禁止在调用函数中使用被调用函数返回值。为使程序降低犯错,凡不要求带回函数值函数,普通应定义为"void"类型。printstar(){printf("************\n");}voidswap(intx,inty){inttemp;temp=x;x=y;y=temp;}第22页经过return语句只能返回一个数值。函数内可有多条返回语句,但每条返回语句返回值只有一个。当函数不需指明返回值时,能够写成:

return;当函数中无返回语句时,表示最终一条语句执行完后遇

}

自动返回。说明:第23页函数调用函数调用是使函数进行一次实际执行。格式:函数名(实际参数表)说明实参在调用时必须有确定值,能够是常量、变量和表示式。函数实参和形参应在个数、类型和次序上一一对应,不然会发生类型不匹配错误。对于无参函数,调用时实参表列为空,但()不能省 。第24页按函数在程序中出现位置有以下3种函数调用方式:函数调用方式

1.函数语句调用把函数调用作为一个语句不要求函数带回明确返回值只完成一定操作#include<stdio.h>voidprintstar(){printf("*************\n");}voidprint_message(){printf("Howareyou!\n");}main(){printstar();print_message();printstar();}第25页2.函数表示式调用以表示式形式出现在程序中要求函数必须带回确定返回值c=2*max(a,b);3.函数参数调用作为参数出现在程序中要求函数必须带回确定返回值m=max(a,max(b,c));第26页函数调用过程1.依据函数名找到被调函数,若没找到,系统将汇报犯错信息;若找到,为形参开辟存放空间;2.计算实参值。将实参值传递给形参;3.保护主调函数现场,中止主调函数,转到被调函数函数体中开始执行;4.碰到return语句或函数结束花括号时,返回主调函数;5.释放形参和调用函数中暂时变量内存空间;6.恢复现场从主调函数中止处继续执行。函数开始调用函数结束调用第27页#include<stdio.h>floataverage(floatx,floaty,floatz)

{floataver;aver=(x+y+z)/3;return(aver);}main(){floata,b,c,ave;a=6.5;b=4.2;c=25.3;

ave=average(a,b,c);

printf(“average=%f”,ave);}mainaverage12.0ave25.3c4.2b6.5aaver12.0z25.3y4.2x6.5第28页函数之间位置关系在一个程序中有多个函数,那么,各函数之间前后位置关系要求以下:

1、被调函数在前面,主调函数在后面.即先定义后调用。2、主调函数在前面,被调函数在后面。这时,必须在调用语句之前,对被调用函数进行原型申明(说明),可在主调函数说明部分,也可在程序开始处说明部分进行。3、被调函数是库函数或另一文件中自定义函数,则在本程序文件起始部分用#include命令将对应文件包含到本文件中来。第29页intadd(intx,inty){return(x+y);}main(){inta=10,b=24,sum;printf("inputa,b:");sum=add(a,b);printf(”sum=%d\n",sum);}main(){inta=10,b=24,sum;

printf("inputa,b:");sum=add(a,b);printf(”sum=%d\n",sum);}intadd(intx,inty){return(x+y);}intadd(intx,inty);intadd(intx,inty);第30页函数原型申明方法惯用是:用函数定义中函数首部,再加上一个分号;也能够省略函数首部中形参名,但必须保留形参类型。longfac();…

/*对除main之外全部自定义函数进行原型说明*/intcmn(intm,intn);main()/*main函数*/{intm,n,c;…}longfac(intx)/*fac函数*/{…}intcmn(intm,intn);/*cmn函数*/

{…}/*也能够写成longfac(int);*//*也能够写成intcmn(int,int);*/第31页例:

longfac(intx);

/*函数原型说明*/main(){intm,n,c;printf("inputm,n:");scanf("%d%d",&m,&n);if(m>n){c=fac(m)/(fac(n)*fac(m-n));/*三次调用*/printf("c(%d,%d)=%d\n",m,n,c);}elseprintf("inputdataerror\n");}longfac(intx){inti;longf=1;for(i=1;i<=x;i++)f=f*i;return(f);}第32页数组作为函数参数

数组元素作函数实参

一维数组名作函数参数

多维数组名作函数参数第33页例:计算数组中相邻两元素之间差值。数组元素作函数实参——值传递intdif(intx,inty){returnx-y;}main(){inti,a[4]={0,1,2,3};for(i=0;i<3;i++){printf("thediffbetween%dand%dis",i,i+1);

printf("%d\n",dif(a[i],a[i+1])

);}}thediffbetween0and1is-1thediffbetween1and2is-1thediffbetween2and3is-1第34页数组名作函数参数——地址传递在主调函数与被调函数分别定义数组,且类型应一致。形参数组大小(多维数组第一维)可不指定,但[]不能省。编译程序并不为形参数组分配空间。数组名表示数组在内存中起始地址。第35页例:从键盘输入8学生成绩,编写函数使用简

单项选择择排序将成绩由高到低排序,并输出成绩。#defineN10voidSelectSort(inta[],intn);voidInputArray(inta[],intn);voidOutputArray(inta[],intn);main(){ intn=8,score[N];

InputArray(score,n); SelectSort(score,n); OutputArray(score,n);}第36页voidInputArray(inta[],intn){ inti; printf("Input%dscores:\n",n); for(i=0;i<n;i++) scanf("%d",&a[i]);}voidOutputArray(inta[],intn){ inti; printf("Thesortedscores:\n"); for(i=0;i<n;i++) printf("%4d",a[i]);}第37页voidSelectSort(inta[],intn){ inti,j,k,t; for(i=0;i<n-1;i++) { k=i; for(j=i+1;j<n;j++) { if(a[k]<a[j]) k=j; } if(k!=i) { t=a[i];a[i]=a[k]; a[k]=t;} }}第38页用数组名作函数参数,应该在主调函数和被调函数分别定义数组,不能只在一方定义;实参数组与形参数组类型应一致;形参数组也能够不指定大小,在定义数组时在数组名后面跟一个[];为了在被调用函数中处理数组元素需要,将数组个数作为一个参数;用数组名作函数实参时,不是把数组值传递给形参,而是把实参数组起始地址传递给形参数组,这么两个数组就共占同一段内存单元。说明:第39页例:求数组中全部元素最大值。intgetmax(intb[3][4])/*或intgetmax(intb[][4])*/{inti,j,max=b[0][0];for(i=0;i<3;i++);{for(j=0;j<4;j++)if(max<b[i][j])max=b[i][j];}returnmax;}main(){inta[3][4],i,j;printf(“\nEnter6integers:");for(i=0;i<3;i++)for(j=0;j<4;j++) scanf("%d",&a[i][j]);printf(“\nMax=%d”,getmax(a));}第40页7.6函数嵌套与递归7.4.1函数嵌套调用

C语言函数定义都是相互平行、独立,也就是说在定义函数时,一个函数内不能包含另一个函数。

但可嵌套调用函数,即在主调函数调用被调函数过程中,被调函数又调用了另一被调函数。

a函数main()调用函数a调用函数bb函数结束第41页

图示是两层嵌套(连main函数共3层函数),其执行过程是:

①执行main函数开头部分;

②遇函数调用a操作语句,流程转去a函数;

③执行a函数开头部分;

④遇调用b函数操作语句,流程转去函数b;

⑤执行b函数,假如再无其它嵌套函数,则完成b函数全部操作;

⑥返回调用b函数处,即返回a函数;

⑦继续执行a函数中还未执行部分,直到a函数结束;

⑧返回main函数中调用a函数处;

⑨继续执行main函数剩下部分直到结束。

第42页例:求三个数中最大数和最小数差值。intdif(intx,inty,intz){return

max(x,y,z)-min(x,y,z);

}main(){inta,b,c,d;scanf("%d%d%d",&a,&b,&c);

d=dif(a,b,c);printf("Max-Min=%d\n",d);}intmax(intx,inty,intz){intr;r=x>y?x:y;return(r>z?r:z);}intmin(intx,inty,intz){intr;r=x<y?x:y;return(r<z?r:z);}第43页例:求圆环面积。#include<math.h>#definePI3.1415926floatarea_ring(floatx,floaty);floatarea(floatr);main(){floatr,r1;printf(“inputtowfigure:\n”);scanf(“%f%f”,&r,&r1);printf(“area_ringis%f”,area_ring(r,r1));}floatarea_ring(floatx,floaty){floatc;c=fabs(area(x)-area(y));return(c);}floatarea(floatr){return(PI*r*r);}

第44页函数递归调用

在函数执行过程中又直接或间接调用该函数本身

直接递归调用在函数中直接调用函数本身间接递归调用在函数中调用其它函数,其它函数又调用原函数intf1(intx){inty,z;……

z=f2(y);…….return(2*z);}intf2(intt){inta,c;……

c=f1(a);…….return(3+c);}intf(intx){inty,z;……

z=f(y);…….return(2*z);}C编译系统对递归函数自调用次数没有限制。f()调f调f2调f1f1()f2()第45页例:计算n!。分析:求解n阶乘实际上有两种方法,一个是连乘法,它基于阶乘定义公式:

n!=1*2*3*…*n实现方法是用循环完成。第46页另一个方法基于阶乘递归定义公式:n!=1(n=0)n*(n-1)!(n>1)用函数直接递归调用实现main(){intn;longy;printf("\ninputaintegernumber:\n");scanf("%d",&n);

if(n<0)printf("dataerror\n");

else{y=fac(n);

printf("%d!=%ld",n,y);}}longfac(intn){longf;

if(n==0)f=1;elsef=n*fac(n-1);

return(f);}第47页main()n=1n=2n=3n=4f=24f=6f=2f=1f=4*fac(3)f=3*fac(2)f=2*fac(1)f=1fac(4)注意:

在递归调用过程中,不一样层同名局部变量是不一样变成机器代码后,执行时相当于将其拉成直线(线性程序代码)。第一次调用fac第二次调用fac第三次调用fac第四次调用faclongfac(intn){return((n<=1)?1:fac(n-1)*n);}longfac(intn){longf;if(n<=1)f=1;elsef=fac(n-1)*n;return(f);}第48页main(){intn;longy;printf("\ninputanintegernumber:\n");scanf("%d",&n);if(n<0)printf("dataerror\n");else{y=fac(4);

longfac(4) {longf; if(4<=1)f=1; elsef=fac(4-1)*4;

longfac(3) {longf; if(3<=1)f=1; elsef=fac(3-1)*3;

longfac(2){longf;if(2<=1)f=1;elsef=fac(2-1)*2; longfac(1) {longf; if(1<=1)f=1; else f=fac(n-1)*n; return(1); }

return(2);} return(6); }

return(24); } printf("%d!=%ld",n,y);}第49页例:Hanoi塔问题。一块板上有三根杆,a,b,c。a杆上套有64个圆盘,大在下,小在上。要把这64个圆盘从a杆移动c杆上,每次只能移动一个圆盘,b杆能够暂时存放。但在任何时候,任何杆上圆盘都必须保持大盘在下,小盘在上。第50页将A塔上红、黄两盘移动到B上蓝盘放到C上将红、黄两盘从B移动到C盘上。(完成)A问题分析:n=1时,直接将其从A--->C

;n>1时,只要先将前n-1个借助C从A--->B,那么能够把第n个直接从A--->C;将剩下n-1个借助A从B--->C,问题性质相同,所以适合采取递归过程!递归结束条件问题分解BC第51页设将n个盘从a借助b移到c杆算法为move(n,a,b,c),则:移动盘子算法以下:①把a上面n-1个盘借助c移到b,记做

move(n-1,a,c,b);②把最下面1个盘从a直接移到c;③把b上n-1个盘借助a移到c,记做

move(n-1,b,a,c);显然这是一个递归算法,按此算法编程以下:第52页main(){intm;printf("\nInputnumber:");scanf("%d",&n);printf("thesteptomoving%2ddiskes:\n",m);

move(n,'a','b','c');}voidmove(intn,intx,inty,intz){if(n==1)printf("%c->%c\n",x,z);

else{move(n-1,x,z,y);printf("%c--->%c\n",x,z);move(n-1,y,x,z);}}第53页…...move(3,'a','b','c');…...move(n,x,y,z);3,'a','b','c'n!=1move(n-1,x,z,y);printf("->",x,z);move(n-1,y,x,z);move(n,x,y,z);2,'a',‘c',‘b'n!=1move(n-1,x,z,y);printf("->",x,z);move(n-1,y,x,z);move(n,x,y,z);1,'a',‘b',‘c'2,'a',‘c',‘b'1,'a',‘b',‘c'n=1printf("->",x,z);1.a->c2.a->bmove(n,x,y,z);1,‘c',‘a',‘b'1,‘c',‘a',‘b'n=1printf("->",x,z);3.c->b4.a->cmove(n,x,y,z);2,‘b',‘a',‘c'2,‘b',‘a',‘c'n!=1move(n-1,x,z,y);printf("->",x,z);move(n-1,y,x,z);move(n,x,y,z);1,‘b',‘c',‘a'1,‘b',‘c',‘a'n=1printf("->",x,z);5.b->a6.b->cmove(n,x,y,z);1,‘a',‘b',‘c'1,‘a',‘b',‘c'n=1printf("->",x,z);7.a->c第54页局部变量和全

温馨提示

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

评论

0/150

提交评论