【文档说明】C语言程序设计第7章函数进阶和结构化编程课件.ppt,共(55)页,1007.851 KB,由小橙橙上传
转载请保留链接:https://www.ichengzhen.cn/view-44490.html
以下为本文档部分文字说明:
第7章函数进阶和结构化编程1完整版ppt学习目标1.掌握源程序结构中函数的组织方法;2.理解结构化程序设计思想,并能利用它来解决问题;3.理解函数嵌套调用的概念,并能熟练利用函数的嵌套调用来解决问题;4.理解递推、递归及其算法实现;5.理解编译预
处理的概念,能熟练应用宏定义和文件包含;6.了解用户自定义库模块。2完整版ppt7.1结构化编程结构化程序设计(StructuredProgramming)是一种良好的程序设计技术,它由著名计算机科学家E·W·D
ijkstra于1969年提出7.1.1自顶向下分析问题自顶向下分析问题就是把一个较大的复杂问题分解成几个小问题后再解决。待解决的问题模块2模块1模块3模块2.1模块2.23完整版ppt7.1.2模块化设计模块化设计时要遵循模块独立性的原则,即模块之间的联系应该尽量简单。具体
体现在:1.一个模块只完成一个指定的功能2.模块间只通过参数进行调用3.一个模块只有一个入口和一个出口4.模块内慎用全局变量在C语言中,模块一般通过函数来实现,一个模块对应一个函数。4完整版ppt7.1.3结构化编码经模块化设计后,每个模块都可以独立编码。编程时应选用顺序、选择和循环3种控
制结构,并使程序具有良好的风格。1.见名知义命名对象名2.使用注释3.使程序结构清晰4.使程序具有良好的交互性5完整版ppt例:读入一组整数存入一个整型数组中,要求显示出计数、当前整数、当前数为止的所
有整数之和、当前数为止的最小整数以及当前数为止的最大整数。除此之外,假设必须要显示如下所示的标题及标题下方分列显示的信息。*******************************************************runningsums,minimums,and
maximums*******************************************************CountItemSumMinimumMaximum6完整版ppt预处理命令/函数原型声明/
主函数:#include<stdio.h>#include<stdlib.h>voidprn_banner(void);/*函数声明*/voidprn_headings(void);/*函数声明*/voidread_and_prn_data(v
oid);/*函数声明*/voidmain(void){prn_banner();prn_headings();read_and_prn_data();}7完整版ppt显示标题函数:voidprn_banner(void){printf("\n**************************
*************************");printf("\nrunningsums,minimums,andmaximums");printf("\n**************************
*************************\n");}显示各列上部的标题函数:voidprn_headings(void){printf("%5s%12s%12s","Count","Item","Sum");
printf("%12s%12s\n\n","Minimum","Maximum");}初始化数据并按要求显示函数:voidread_and_prn_data(void){inti,sum,smallest,biggest;inta[10]={1,2,6,7,0,-6,19,52,10
,-10};sum=0;smallest=biggest=a[0];for(i=0;i<10;i++){sum+=a[i];smallest=min(a[i],smallest);biggest=max(a[i],biggest);printf("%5d%12d%12d%
12d%12d\n",i+1,a[i],sum,smallest,biggest);}}8完整版ppt7.2函数的嵌套调用main函数调用a函数结束a函数调用b函数b函数a函数结束b函数结束函数嵌套调用结构示意图9完整版ppt例:求组合数。#include<stdio.h>f
loatfac(intn){inti;floatf=1;for(i=2;i<=n;i++)f*=i;returnf;}floatcmn(intm,intn){floatres;res=fac(m)/(fac(n)*fac(m-n));return
res;}voidmain(){intm,n;floatt;printf("Inputm&n:");scanf("%d%d",&m,&n);t=cmn(m,n);printf("C(%d,%d)=%10.0f\n",m,n,t
);}10完整版ppt例:设计一个用于计算常用圆形体体积的计算器,该计算器可支持多次反复计算。采用菜单方式输入1或2或3,分别表示需要计算球体、圆柱体和圆锥体的体积,计算时需输入函数所需的相应参数。main函数calcula
te函数vol_cylind函数vol_ball函数vol_cone函数圆形体体积计算器函数调用结构11完整版ppt#include<stdio.h>#include<math.h>#definePI3.141592654voidc
alculate(int);voidmain(void){intsel;/*循环选择计算圆形体的体积,直到输入非1~3数字为止*/while(1){printf("\t\t%s","1--ball\n");printf("\t\t%s","2--
cylind\n");printf("\t\t%s","3--cone\n");printf("\t\t%s","other--exit\n");printf("\t\tPleaseinputyourselete:");scanf("
%d",&sel);if(sel<1||sel>3){printf("\ninputerror\npleaseinput1~3\n");break;}elsecalculate(sel);}}12完整版pptvoidcalculate(intsel){doublevol_ball(
void);doublevol_cylind(void);doublevol_cone(void);switch(sel){case1:printf("ball:%.2lf\n",vol_ball());break;case2:prin
tf("cylind:%.2lf\n",vol_cylind());break;case3:printf("cone:%.2lf\n",vol_cone());break;}}/*ball:v=4/3*PI*r*r*r*/doublevol_ball(){doubler;printf("
Pleaseinputr:");scanf("%lf",&r);return4.0/3*PI*r*r*r;}13完整版ppt/*cylind:v=PI*r*r*h*/doublevol_cylind(){doubler,h;printf("Pleaseinputr&h
:");scanf("%lf%lf",&r,&h);returnPI*r*r*h;}/*cone:v=PI*r*r*h/3.0*/doublevol_cone(){doubler,h;printf("Pleaseinputr&h:");scanf("%lf%lf",&r
,&h);returnPI*r*r*h/3.0;}14完整版ppt7.3递推7.3.1递推的一般概念递推也称为迭代,思路是通过数学推导,将一个复杂的运算化解为若干简单运算的重复执行。例:通过公式:计算的近似值,计算过程在所加项的值小于10-10时终止
。753217165432121514321213121216…15完整版ppt#include<stdio.h>doublefun(double);voidmain(){doubleeps=1e-10,s
um;sum=fun(eps);printf("\nPI=%.8lf",sum);}doublefun(doubleeps){doublesum=0.5,t,t1,t2,t3;intodd=1,even=2;t=t1=t2=1
.0;t3=0.5;while(t>1e-10){t1=t1*(even-1)/even;odd+=2;even+=2;t2=1.0/odd;t3=t3/4.0;t=t1*t2*t3;sum+=t;}returnsum*6;}16完整版ppt例:A、B、C、D、E合伙夜间捕鱼,凌晨时都
已疲惫不堪,各自在河边的树丛中找地方睡着了。目上三竿,A第一个醒来,他将鱼平分作5份,把多余的一条扔回湖中,拿自己的一份回家去了;B第二个醒来,也将鱼平分作5份,把多余的一条扔回湖中,只拿自己的一份;接着C、D、E依次醒来,也都按同样的办法分鱼。问5人至
少合伙捕到多少条鱼?每个人醒来后看到的鱼数是多少条?17完整版pptfish[1]=5人所捕的总鱼数fish[2]=(fish[1]-1)*4/5fish[3]=(fish[2]-1)*4/5fish[4]=(fish[3]-1)*4/5fish[5]=(fish[4]-1)*4/5写成一
般式为:fish[i]=(fish[i-1]-1)*4/5i=2,3,…,5intfish[6]={1,1,1,1,1,1},ifish[5]=fish[5]+5for(i=4;i>0;i--)fish[i
+1]%5==1YNbreakfish[i]=fish[i+1]*5/4+1当fish[1]==1||fish[1]%5!=1输出计算结果fish[1]~fish[5]18完整版ppt#include<stdi
o.h>voidmain(){intfish[6]={1,1,1,1,1,1},i;do{fish[5]=fish[5]+5;for(i=4;i>0;i--){if(fish[i+1]%5==1)fish[i]=fish[i+1]*5/4+1;e
lsebreak;}}while(fish[1]==1||fish[1]%5!=1);for(i=1;i<=5;i++)printf("%10d",fish[i]);printf("\n");}19完整版ppt7.3.2递推数列如果一个数列从某一项起,它的任何一项都可以用它前面的若干项来确定,这样
的数列被称为递推数列,表示某项与其前面的若干项的关系就称为递推公式。例如Fibonacci数列如下:1,1,2,3,5,8,13,„,令fib(n)表示Fibonacci数列的第n项,依据数列中项与项之间的关系可写出如下Fibonacci数列的递推公式:fib(n)=fib(n-1
)+fib(n-2)n=3,4,„(通项公式)fib(1)=fib(2)=1(边界条件)20完整版ppt7.3.3递推算法的程序实现例:王小二自夸刀工不错,有人放一张大的煎饼在砧板上,问他:“饼不许离开砧板,切100刀最多能分成多少块?”q(1)=1+1=2q(2)=1+1+2=4
q(3)=1+1+2+3=7q(4)=1+1+2+3+4=11用归纳法不难得出:q(n)=q(n-1)+n(通项公式)q(0)=1(边界条件,一刀不切只有一块)切1刀切饼问题示意图切2刀切3刀切4刀21完整版ppt#include<stdio.h>#include<co
nio.h>#defineN100voidmain(){inti,q[101];q[0]=1;for(i=1;i<=N;i++)q[i]=q[i-1]+i;printf("%d",q[N]);}22完整版ppt7.4递归调用7.4.1递归函数的执行过程如果函数直接或间接地对自己进行调用,就说
函数是递归的(分别称为直接递归和间接递归)。在C语言中,所有的函数都可以递归地使用,直接递归是最简单的形式。23完整版ppt例:在屏幕上以降序形式依次显示1--10之间的整数。#include<stdio.
h>voidfun(int);voidmain(void){fun(10);}voidfun(intn){if(n){printf("%3d",n);fun(n-1);}elseprintf("\nEND!");}24完整版ppt例:计算前n个正整数之和。#include<stdio.h
>voidmain(){printf("%d",sum(4));}intsum(intn){if(n<=1)returnn;elsereturn(n+sum(n-1));}函数调用返回值sum(1)1sum(2)2+su
m(1)即2+1sum(3)3+sum(2)即3+2+1sum(4)4+sum(3)即4+3+2+125完整版ppt7.4.2递归问题求解例:有5个人坐在一起,问第5个人多少岁?他说比第4个人大2岁;问第4个人多少岁?他说比第3个人大2岁;问第3个人多少岁?他
说比第2个人大2岁;问第2个人多少岁?他说比第1个人大2岁;问第1个人,他说是10岁。请问第5个人多大?分析: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(n>1)26完整版pptage(5)=age(4)+2age(4)=age(3)+2age(3)=age(2)+2age(2)=age(1)+2age(1)=10age(2)=12age(
3)=14age(4)=16age(5)=18求年龄的递归调用过程27完整版ppt#include"stdio.h"intage(intn){intc;if(n==1)c=10;elsec=age(n-1)+2;return(c);}main(){printf("%d",age
(5));}28完整版ppt例:求Fibonacci数列的第40个数。Fibonacci数列有如下特点:第1、第2个数均为1,从第3个数开始的每一个数均是其前两个数之和。即:F1=1(n=1)F2=1(n=2)Fn=Fn-1+Fn-2(
n≥3)分析:根据任务要求,求Fibonacci数列可以用下列递归公式表示1(n=1,2)Fn=Fn-1+Fn-2(n≥3)29完整版ppt#include<stdio.h>longfib(intt){longintc;if
(t==1||t==2)c=1;elsec=fib(t-1)+fib(t-2);returnc;}voidmain(){printf("%10ld",fib(40));}30完整版ppt例:Hanoi塔问题。相传在古代印度的Bramah庙中,有
位僧人整天把3根柱子上的金盘倒来倒去,原来他是想把64只一个比一个大的金盘从一根柱子上移到另一根柱子上去,移动过程要遵循下列规则:(1)每次只允许移动一只盘;(2)任何时刻任何柱子上都不允许大盘摞在小盘的上面。如图7.7所示。ABC汉诺塔31完整版ppt分析如下:1.如果
n=1,并假定盘号为1,则将盘1从A直接移动到C。2.如果n=2,则:(1)将A上的n-1(等于1)个盘移到B上;(2)再将A上的一个盘移到C上;(3)最后将B上的n-1(等于1)个盘移到C上。3.如
果n=3,则:(1)将A上的n-1(等于2,令其为n`)个盘移到B(借助于C)①将A上的n-1(等于1)个盘移到C上;②将A上的一个盘移到B上;③将C上的n-1(等于1)个盘移到B上。(2)将A上的一个盘
移到C(3)将B上的n-1(等于2,令其为n)个盘移到C(借助A)①将B上的n-1(等于1)个盘移到A;②将B上的一个盘移到C;③将A上的n-1(等于1)个盘移到C。32完整版ppt从上面分析可以看出,当n大
于等于2时,移动的过程可分解为三个步骤:第一步:把A上的n-1个盘借助C移到B上;第二步:把A上的一个盘移到C上;第三步:把B上的n-1个盘借助A移到C上。其中第一步和第三步是类同的,可以用递归解决。递归函数中使用了四个参数:(
1)准备移动的盘数;(2)最初放臵这些盘的柱子;(3)最后放臵这些盘的柱子;(4)临时存放的柱子。33完整版ppt#include"stdio.h"voidmove(charx,chary){printf("%c-->%c\n",x,y);}voidha
noi(intn,charone,chartwo,charthree)/*将n个盘从one柱借助two柱,移到three柱*/{if(n==1)move(one,three);else{hanoi(n-1
,one,three,two);move(one,three);hanoi(n-1,two,one,three);}}voidmain(){intm;printf("inputthenumberofdiskes:");scanf("%d",&m);printf("thesteptomoving%3
ddiskes:\n",m);hanoi(m,'A','B','C');}34完整版ppt7.4.3递归算法举例例:在屏幕上绘制图案#include<stdio.h>#defineSYMBOL'*'#defineOFFSET0#defineLENGTH19voiddisplay(char,in
t,int);voiddraw(char,int);voidmain(void){display(SYMBOL,OFFSET,LENGTH);}voiddisplay(charc,intm,intn){if(n>0)
{draw('',m);draw(c,n);putchar('\n');display(c,m+1,n-2);}}voiddraw(charc,intk){if(k>0){putchar(c);draw(c,k-1);}}运行结果:***********
*************************35完整版ppt例:用递归处理串:(1)求串长(2)模拟字符串比较函数。(1)用递归求串长#include<stdio.h>voidmain(void){charstr[]="OneWorld!OneDream!";printf("%
d\n",r_strlen(str));}intr_strlen(chars[]){if(*s=='\0')return0;elsereturn1+r_strlen(s+1);}36完整版ppt(2)用递归模拟
字符串比较函数#include<stdio.h>voidmain(void){charstr1[]="OneWorld!",str2[]="OneDream!";printf("%d\n",r_strncmp(str1,str2,10));
}/*Recursivestringncompare.*/intr_strncmp(char*s1,char*s2,intn){if(*s1!=*s2||*s1=='\0'||n==1)return*s1-*s2;el
sereturnr_strncmp(++s1,++s2,--n);}37完整版ppt例:整型数组a有n个元素值,求其中的最大数和最小数。#include<stdio.h>#include<stdlib.h>/*stdlib.h是杂项说明,内含求两数中的大数、求两数中的小数等函数原型说明
*/voidminmax(inta[],intn,int*min_ptr,int*max_ptr){intmin1,max1,min2,max2;if(n==1)*min_ptr=*max_ptr=a[0];/*子问题只有一个元素的情况*/elseif(n==
2)/*子问题有两个元素的情况*/{*min_ptr=min(a[0],a[1]);*max_ptr=max(a[0],a[1]);}else{minmax(a,n/2,&min1,&max1);/*求前半部分中的最小值和最大值*/minmax(a+n/2,n-n/2,&min2,&
max2);/*求后半部分中的最小值和最大值*/*min_ptr=min(min1,min2);/*两部分中最小值中的较小者赋给min_ptr指向的对象*/*max_ptr=max(max1,max2);/*两部分中最大值中的较大者赋
给max_ptr指向的对象*/}}voidmain(){inta[10]={87,13,556,673,849,643,394,583,523,3};intfmin,fmax;minmax(a,10,&fmin,&fmax);
printf("minis:%d\nmaxis:%d\n",fmin,fmax);}38完整版ppt7.5编译预处理7.5.1预处理的概念预处理:在C编译系统对程序进行通常的编译前,先对程序中以“#”开头的命令进行的特殊处理。然后再将这些预处理的结果和源程序一起再进行通常的编
译处理,从而得到目标代码。一条预处理命令以“#”开头,且占用单一的书写行;预处理命令一般放在源程序的前面,且一般不以“;”结束。39完整版ppt7.5.2宏定义宏:代表一个字符串的标识符;宏名:被定义为“宏”的标识符;宏代换(宏展开):在编译预处理
时,对程序中所有出的“宏名”,用宏定义中的字符串去代换的过程。一、宏替换1.无参宏的定义格式:#define标识符字符串如:(1)#definePI3.1415926(2)#defineM(y*y+3*y)40完整版ppt例:由键盘输入y值,求表达式:3(y2+3y)+4(y2+3y)+5(y
2+3y)#defineM(y*y+3*y)main(){ints,y;printf(“Inputanumber:”);scanf(“%d”,&y);s=3*M+4*M+5*M;printf(“s=%d\n”,s);}先宏展开
:s=3*(y*y+3*y)+4*(y*y+3*y)+5*(y*y+3*y)再与源程序一起编译。41完整版ppt说明:1.宏定义中表达式两边的括号不能省;2.宏名习惯上用大写字母;3.使用宏名使程序易读、易修改;4.宏定义不
是说明或语句,不作语法检查;如:#definePI3.14I59265.宏名的作用域一般自定义起到本源程序结束;6.可用#undef宏定义的作用域;如:#defineG9.8main(){…}#undefGf1()…42完整版ppt7.宏定义允许嵌套;如:#definePI3.141592
6#defineSPI*y*y…printf(“%f”,S);…8.宏名在源程序中若用引号括起来,则TC中预处理不对其作宏代换;如:#defineOK100main(){printf(“OK”);prinf(“\n”);}43完整版ppt9.对“输出格式”进行宏定义,可以减少书写麻烦;如:#de
finePprintf#defineD“%d,%d,%d\n”#defineF“%6.2f,%6.2f,%6.2f\n”main(){inta=5,c=8,e=11;floatb=3.8,d=9.7,f=21.08;P(D,a,c,e);P(F,b,d,f);P(F,a+b,
c+d,e+f);}44完整版ppt二、有参宏格式:#define宏名(参数1,参数2,„,参数n)字符串如:#defineS(a,b)a*b…area=S(3,2);…再如:#defineM(y)y*y+3*y…k=M(5);
…45完整版ppt例:利用宏定义求两个数中的大数。#defineMAX(a,b)(a>b)?a:bmain(){intx,y,max;scanf(“%d%d”,&x,&y);max=MAX(x,y);printf(“max=%d\n”,max
);}本例中宏展开后的语句为:max=(x>y)?x:y用于计算x、y中的大者。46完整版ppt例:#definePI3.1415926#defineS(r)PI*r*rmain(){floata,area;a=3.6;area=S(a);printf(“r=%f\n
area=%f\n”,a,area);}47完整版ppt说明:1.带参宏定义中,宏名与参数间不能有空格;2.如上例程序改为:#definePI3.1415926#defineS(r)PI*r*rmain(){floata,b,a
rea;a=3.6;b=4.1;area=S(a+b);printf(“r=%f\narea=%f\n”,a+b,area);}则宏展开为:area=3.1415926*a+b*a+b48完整版ppt3.带参宏定义,形参不分
配内存单元,因此不必作类型定义(与函数区别之一);4.带参宏与函数的区别之二:main(){inti=1;while(i<=5)printf(“%d\n”,SQ(i++));}SQ(inty){return(y)*(y);}#defineSQ(y)((y)*(y
))main(){inti=1;while(i<=5)printf(“%d\n”,SQ(i++));}14916252123049完整版ppt函数和带参数宏的区别区别类型函数带参数的宏是否计算实参的值先计算出实参表达式
的值,然后传给形参不计算实参表达式的值,直接用实参进行简单的替换。何时进行处理、分配内存单元在程序运行时进行值的处理、分配临时的内存单元。编译前,由预处理程序进行宏展开,不分配内存单元。不进行值的处理类型要求实参和形参要定义类型
,且类型一致。不存在类型问题,只是一个符号表示。调用情况函数的代码只作为一个拷贝存在,对程序较大、调用次数多的较合算,但调用函数时有一定数量的处理开销。在源代码中遇到宏定义时,都将其扩展为代码,程序调用几次宏就扩展为代
码几次,但调用宏时没有处理的开销。50完整版ppt7.5.3文件包含文件包含是C预处理程序的另一个重要功能。文件包含命令行的一般形式为:#include"需包含的文件名"或#include<需包含的文件名>例如:#include"stdio.h"#include<m
ath.h>51完整版ppt说明:(1)包含命令中的文件名可以用双引号括起来,也可以用尖括号括起来,但这两种形式是有区别的:使用尖括号(<„>):表示预处理程序在规定的磁盘目录(通常为include子目录)查找文件。使用双引号(“„”):表示预处
理程序首先在当前目录中查找文件,若没有找到,最后才去include子目录中查找。(2)一个include命令只能指定一个被包含文件,若有多个文件要包含,则需用多个include命令。(3)文件包含允许嵌套,即在一个被包含的文件中又可以包含另一个文件。52完整版ppt例:设有如下直接选择
排序函数:voidsel_sort(inta[],intn){inti,j,k,temp;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){temp=a[k];a[k]=a
[i];a[i]=temp;}}}现将其以文件名sort.c存放在win-tc\projects(Win-TC环境下)当前工作目录下,要求通过文件包含的方法对一个具有10个元素值的整型数组实现排序。53完整版ppt#include<s
tdio.h>#include"sort.C“/*第3条包含命令包含了编程者自己设计的文件,必须存在于当前工作目录下*/voidmain(void){inti,a[10]={8,3,7,9,10,-5,7,15,90,76};sel_sort(a,10);for(i=0;i<10
;i++)printf("%5d",a[i]);printf("\n");}54完整版ppt此课件下载可自行编辑修改,供参考!感谢您的支持,我们努力做得更好!