C语言程序设计教程第6章(精)ppt课件_第1页
C语言程序设计教程第6章(精)ppt课件_第2页
C语言程序设计教程第6章(精)ppt课件_第3页
C语言程序设计教程第6章(精)ppt课件_第4页
C语言程序设计教程第6章(精)ppt课件_第5页
已阅读5页,还剩76页未读 继续免费阅读

下载本文档

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

文档简介

第六章函数与编译预处理,6.1模块化程序设计与函数6.2函数的定义与调用6.3函数的递归调用6.4变量的作用域与存取方式6.5编译预处理,C语言程序设计教程,2020/5/19,.,2,6.1模块化程序设计与函数,在设计较复杂的程序时,我们一般采用的方法是:把问题分成几个部分,每部分又可分成更细的若干小部分,逐步细化,直至分解成很容易求解的小问题。这样的话,原来问题的解就可以用这些小问题来表示。,2020/5/19,.,3,基本概念,2020/5/19,.,4,模块与函数,C语言程序由基本语句和函数组成,每个函数可完成相对独立的任务,依一定的规则调用这些函数,就组成了解决某个特定问题的程序。,2020/5/19,.,5,模块与函数,把大任务分解成若干功能模块,用多个函数来实现这些功能模块。通过函数的调用来实现完成大任务的全部功能。,2020/5/19,.,6,模块与函数,任务、模块与函数的关系:一个大任务分成多个功能模块,功能模块则由一个或多函数实现。模块化的程序设计是靠设计函数和调用函数实现的。,2020/5/19,.,7,例:分数排序,任务:输入三个数,从大到小的顺序的输出。如果大于等于85,在该数后面输出A,小于85且大于等于70,则输出B,小于70且大于等于60,输出C,如果小于60,则输出D。,思路:scanf()输入分数另建一个排序函数判断并输出等级函数打印分数及等级的函数,虽然也可以由一个主函数来完成,但这样做可读性及操作性会更好。,2020/5/19,.,8,voidmain()floata,b,c;scanf(%f,%f,%f,/*输出a,b,c三个数*/,2020/5/19,.,9,voidsortabc(a,b,c)float*a,*b,*c;floatt;if(*a*b)t=*a;*a=*b;*b=t;/*交换a,和b的值*/if(*b=70)return(B);elseif(x=60)return(C);elsereturn(D);,2020/5/19,.,11,voidputabc(a,b,c)floata,b,c;charg;g=grade(a);/*判别等级*/printf(%6.1f:%c,a,g);g=grade(b);printf(%6.1f:%c,b,g);g=grade(c);printf(%6.1f:%c,c,g);,2020/5/19,.,12,模块设计的原则,模块独立,规模适当,层次分明,功能专一,2020/5/19,.,13,独立性原则表现在模块完成独立的功能,和其它模块间的关系简单,各模块可以单独调试。修改某一模块,不会造成整个程序的混乱。,每个模块完成一个相对独立的特定子功能。在对任务逐步分解时,要注意对问题的综合。例如,一些模块的相似的子任务,可以把它们综合起来考虑,找出它们的共性,把它们做成一个完成特定任务的单独模块。,每个模块有特定功能,2020/5/19,.,14,2020/5/19,.,15,2020/5/19,.,16,模块不能太大,但也不能太小。模块的功能复杂,可读性就不好,而且也违背独立性原则。但如果做得太小,实际上也会复杂各个模块间反复调用,可读性也会降低。这点需要慢慢积累经验,好好把握。,2020/5/19,.,17,算法简介,算法简介,算法简介,什么是算法?,通俗地说,算法是解决一类特定问题的方法和步骤。,算法是一个有限操作的序列。,算法的每一步都是确定的。,算法的每一步计算机都能操作。,有一个或多个的输入或输出。,2020/5/19,.,18,算法的描述,算法描述的任务是将解题步骤和方法用一定的形式表示出来,要清楚、准确、严谨,还要可读性好,方便实现。算法两大要素:一是操作,用类计算机语句或自然语言描述。二是控制结构,描述算法一般可以用流程图描述。,2020/5/19,.,19,例6.2设计算法:找出a,b两数中的较大者,并输出,分析:这个问题分三个步骤:输入两个数;找出其中的大数;输出大数。,2020/5/19,.,20,开始,输入a,b,a=A,2020/5/19,.,25,“函数”的主要知识点,函数的定义函数的参数和返回值函数的调用嵌套和递归变量的作用域,2020/5/19,.,26,函数举例,#includemain()inta,b,m;/*说明变量*/intmax(inta,intb);/*函数声明*/scanf(%d,%d,/*调用库函数getch*/,2020/5/19,.,27,函数举例,intmax(inta,intb)/*定义函数max*/inty;y=(ab)?a:b;/*条件表达式*/returny;,2020/5/19,.,28,自定义函数的声明,自定义函数在调用前应先声明。使系统知道将要用到某个函数及它的类型,以便处理。函数声明应与该函数定义时给出的函数类型与名字、形参的个数、类型、次序相一致。,2020/5/19,.,29,求1!+2!+3!+10!,算法i=1;s=0;当i=10s=s+i!定义求i!的函数,2020/5/19,.,30,求1!+2!+3!+10!程序,voidmain()longmm(int);/*自定义求阶乘函数应先声明*/inti;longs=0;for(i=1;i=10;i+)s+=mm(i);/*调用求阶乘函数,求I的阶乘*/printf(“n%ld”,s);,2020/5/19,.,31,定义求n!的函数,longmm(intn)longt=1;inti;for(i=1;ib)?a:b;returny;,调用时:m=max(3,6);m=max(a,b);,2020/5/19,.,33,形式参数与实际参数的关系,形式参数在函数中是变量名,在函数调用时,形参被分配相应的内存实际参数是表达式负责向对应的形参标识的内存单元传递数据实参与形参必须个数相同对应的形参和实参的类型必须一致,2020/5/19,.,34,实参与形参,例:主调函数中有如下语句:scanf(%d,%d,如果输入6,2函数intmax(inta,intb)形参a得到第一个实际参数a的值6形参b得到第二个实际参数b+3的值5,2020/5/19,.,35,函数返回值,函数返回值通过return语句获得函数返回值的类型就是函数的类型returny;将变量y的值返回给调用者returny+3;将表达式的值返回给调用者,2020/5/19,.,36,return的数据类型与函数的类型矛盾时,自动将数据转换成函数的类型,intfunct1()charch;while(ch=getch()z);returnch;调用:i=funct1();/*返回的是int类型*/,2020/5/19,.,37,函数没有返回值,函数定义成空类型,voidputline()inti;for(i=0;i%d”,a,c);hanoi(n-1,b,a,c);,main()intn;printf(“inputn:”);scanf(“%d”,2020/5/19,.,51,递归汉诺塔步骤,voidhanoi(intn,inta,intb,intc)if(n=1)printf(“%d-%d”,a,c);elsehanoi(n-1,a,c,b);printf(“%d-%d”,a,c);hanoi(n-1,b,a,c);,main()intn;printf(“inputn:”);scanf(“%d”,2020/5/19,.,52,递归汉诺塔步骤,voidhanoi(intn,inta,intb,intc)if(n=1)printf(“%d-%d”,a,c);elsehanoi(n-1,a,c,b);printf(“%d-%d”,a,c);hanoi(n-1,b,a,c);,main()intn;printf(“inputn:”);scanf(“%d”,主函数调用hanoi(n,1,2,3);第一次调用。第一次调用hanoi(n,a,b,c)(第一层)即要把三个金片移到c,n=3,2020/5/19,.,53,递归汉诺塔步骤,voidhanoi(intn,inta,intb,intc)if(n=1)printf(“%d-%d”,a,c);elsehanoi(n-1,a,c,b);printf(“%d-%d”,a,c);hanoi(n-1,b,a,c);,main()intn;printf(“inputn:”);scanf(“%d”,由于n1则执行hanoi(n-1,a,c,b)(第二次调用),n=3,2020/5/19,.,54,递归汉诺塔步骤,voidhanoi(intn,inta,intb,intc)if(n=1)printf(“%d-%d”,a,c);elsehanoi(n-1,a,c,b);printf(“%d-%d”,a,c);hanoi(n-1,b,a,c);,main()intn;printf(“inputn:”);scanf(“%d”,由于仍然n1则执行hanoi(n-1,a,c,b)(第三次调用),n=2,2020/5/19,.,55,递归汉诺塔步骤,voidhanoi(intn,inta,intb,intc)if(n=1)printf(“%d-%d”,a,c);elsehanoi(n-1,a,c,b);printf(“%d-%d”,a,c);hanoi(n-1,b,a,c);,main()intn;printf(“inputn:”);scanf(“%d”,由于n=1则printf(“%d-%d”,a,c);即把金片从a移动到c,n=1,2020/5/19,.,56,递归汉诺塔步骤,voidhanoi(intn,inta,intb,intc)if(n=1)printf(“%d-%d”,a,c);elsehanoi(n-1,a,c,b);printf(“%d-%d”,a,c);hanoi(n-1,b,a,c);,main()intn;printf(“inputn:”);scanf(“%d”,第三层执行完毕,返回到第二层,即下去执行printf(“%d-%d”,a,c);把第二个金片摆到第二根针上,n=2,2020/5/19,.,57,递归汉诺塔步骤,voidhanoi(intn,inta,intb,intc)if(n=1)printf(“%d-%d”,a,c);elsehanoi(n-1,a,c,b);printf(“%d-%d”,a,c);hanoi(n-1,b,a,c);,main()intn;printf(“inputn:”);scanf(“%d”,执行下一条语句,又调用第三层hanoi(1,3,1,2),n=2,2020/5/19,.,58,递归汉诺塔步骤,voidhanoi(intn,inta,intb,intc)if(n=1)printf(“%d-%d”,a,c);elsehanoi(n-1,a,c,b);printf(“%d-%d”,a,c);hanoi(n-1,b,a,c);,main()intn;printf(“inputn:”);scanf(“%d”,n=1,执行结果为32,n=1,2020/5/19,.,59,递归汉诺塔步骤,voidhanoi(intn,inta,intb,intc)if(n=1)printf(“%d-%d”,a,c);elsehanoi(n-1,a,c,b);printf(“%d-%d”,a,c);hanoi(n-1,b,a,c);,main()intn;printf(“inputn:”);scanf(“%d”,第二层也执行完了,返回第一层,执行接下来的语句,结果为13。,n=3,2020/5/19,.,60,递归汉诺塔步骤,voidhanoi(intn,inta,intb,intc)if(n=1)printf(“%d-%d”,a,c);elsehanoi(n-1,a,c,b);printf(“%d-%d”,a,c);hanoi(n-1,b,a,c);,main()intn;printf(“inputn:”);scanf(“%d”,执行接下来的语句,再次调用第二层hanoi(2,2,1,3),n=3,2020/5/19,.,61,递归汉诺塔步骤,voidhanoi(intn,inta,intb,intc)if(n=1)printf(“%d-%d”,a,c);elsehanoi(n-1,a,c,b);printf(“%d-%d”,a,c);hanoi(n-1,b,a,c);,main()intn;printf(“inputn:”);scanf(“%d”,2020/5/19,.,62,6.4变量的作用域与存储方式,先看一个例子,错在那里?:voidf1()intt=2;a*=t;b/=t;main()inta,b;printf(“Entera,b:”);scanf(“%d,%d”,编译程序会提示出错:Undefinedsymbola和Undefinedsymbolb。为什么?,2020/5/19,.,63,一.变量的作用域即变量的有效范围1.变量按作用域分为全局变量和局部变量2.比较:全局变量(外部变量)局部变量(内部变量)定义位置:函数体外函数体内作用域:从定义处到本源从定义处到本函数结束文件结束举例:所有函数体外定义的变量(1)所有在函数体内定义(2)形式参数,注意与局部变量同名的处理局部变量屏蔽全局变量,不同函数中同名局部变量互不干扰,2020/5/19,.,64,#includeinta,b;/*a,b为全局变量*/voidf1(intx)intt1,t2,a;a=t1=x*4;t2=b*3;b=10;printf(“f1:t1=%d,t2=%d,a=%d,b=%dn”,t1,t2,a,b);main()a=2;b=4;/*此a,b是全局变量,赋值*/f1(a);/*调用函数f1()*/printf(“main:a=%d,b=%d”,a,b);程序输出结果为:,f1:t1=8,t2=12,a=8,b=10main:a=2,b=10,2020/5/19,.,65,若将程序改为:#includeinta=2,b=4;/*a,b为全局变量*/voidf1()intt1,t2;t1=a*2;t2=b*3;b=100;printf(“t1=%d,t2=%d,b=%dn”,t1,t2,b);main()intb=4;/*此b是局部变量,赋值*/f1();/*调用函数f1()*/printf(“a=%d,b=%d”,a,b);,结论:全局变量与局部变量同名时,局部变量起作用,全局变量被屏蔽(不影响),应小心使用,程序输出结果为:t1=4,t2=12,b=100a=2,b=4,2020/5/19,.,66,二.变量的存储特性1.变量按存在时间分静态变量动态变量,静态存储类型的变量的生存期为程序执行的整个过程,在该过程中占有固定的存储空间,通常称它们为永久存储。动态存储类型变量只生存在某一段时间内。例如,函数的形参和函数体或分程序中定义的变量,只是在程序进入该函数或分程序时才分配存储空间,当该函数或分程序执行完后,变量对应的存储空间又被撤销了。2.c语言中每一个变量有两个属性:数据类型,存储特性完整的变量定义:存储特性数据类型变量名;,2020/5/19,.,67,3.变量的存储特性自动型auto静态型static寄存器型register外部型extern(1)auto型每次进入程序是自动分配内存,不长期占用内存例如:形式参数,自动型局部变量(2)static型局部静态变量全局静态变量长期占用内存,2020/5/19,.,68,例1:分析执行结果f(inta)intb=0;staticintc=3;b+;c+;printf(“%5d%5d%5d”,a,b,c);return(a+b+c);main()inta=2,k;for(k=0;k3;k+)printf(“%5dn”,f(a);,静态变量只初始化一次,结果:214(a,b,c)7(f(a)21582169,2020/5/19,.,69,(3)register型将使用频率高的变量定义为register型,可以提高运行速度.数据内存运算器运算器结果控制器数据,寄存器,寄存器变量只限于整型、字符型、指针型的局部变量。寄存器变量是动态变量,而且数目有限,一般仅允许说明两个寄存器变量。例如:registerintd;registercharc;,2020/5/19,.,70,(4)extern型引用:extern类型变量名;如果某个模块文件中要用到另一个模块文件中的全局变量,就要用extern说明例如:程序模块file1.c中定义了全局变量ints;而在另一个程序模块file2.c中的函数fun1()中需要使用这个变量s。为此,可以在file2.c的函数fun1()中加上外部变量说明语句:fun1()externints;/*表明变量s是在其他文件定义的*/.定义时分配内存,其他文件引用时不再分配内存.,2020/5/19,.,71,6.5编译预处理,“编译预处理”是C语言编译系统的一个组成部分。是在编译前由编译系统中的预处理程序对源程序的预处理命令进行加工。,源程序中的预处理命令均以“#”开头,结束不加分号,以区别源程序中的语句,它们可以写在程序中的任何位置,作用域是自出现点到源程序的末尾。预处理命令包括执行宏定义(宏替换)、包含文件和条件编译。,2020/5/19,.,72,一.宏定义简单宏定义1.一般形式为:#define宏名串(宏体)如:#definePI3.14159/*定义后,可以用PI来代替串3.14159*/2.宏定义的作用在宏定义之后,该程序中宏名就代表了该字符串。3.说明可以用#undef命令终止宏定义的作用域。例如:#undefPI宏定义的嵌套使用#defineR3.0#definePI3.1415926#defineL2*PI*R/*宏体是表达式*/#defineSPI*R*R,2020/5/19,.,73,main()printf(L=%fnS=%fn,L,S);/*2*PI*R替换L,PI*R*R替换S*/程序运行结果如下:L=18.849556双引号内与宏同名的字母不作宏展开.(见上例),带参数的宏定义1.带参数的宏定义的一般形式为#define宏名(参数表)字符串如:#defineS(a,b)a*b#definePR(x)printf(s=%fn”,x),2020/5/19,.,74,2.带实参的宏名被展开宏名被所定义的宏体替换,宏体中的形参按从左到右的顺序被实参替换。例如:area=S(3,2);PR(area);展开为:area=3*2;PR(area)展开的结果是:printf(s=%fn”,area);宏定义与函数的区别(1)引用宏只占编译时间,不占运行时间。(2)引用宏没有返回值。如:#definesqu(n)n*nvoidmain(void)printf(%fn,27.0/squ(3.0);程序输出结果为:27.000000,注意,展开为27.0/3.0*3.0不是27.0/(3.0*3.0),如需完成上式,则定义宏时应为#definesqu(n)(n

温馨提示

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

评论

0/150

提交评论