第5章模块化程序设计.ppt

上传人:可****阿 文档编号:88682314 上传时间:2023-04-30 格式:PPT 页数:77 大小:643KB
返回 下载 相关 举报
第5章模块化程序设计.ppt_第1页
第1页 / 共77页
第5章模块化程序设计.ppt_第2页
第2页 / 共77页
点击查看更多>>
资源描述

《第5章模块化程序设计.ppt》由会员分享,可在线阅读,更多相关《第5章模块化程序设计.ppt(77页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。

1、1第第5 5章章 模块化程序设计模块化程序设计C C/C C+语言程序设计案例教程语言程序设计案例教程第第5章章 函数函数2023/4/2725.1 C程序结构程序结构5.2 函数的定义函数的定义5.3 函数调用和函数说明函数调用和函数说明5.4 函数的嵌套调用和递归调用函数的嵌套调用和递归调用5.5 变量的作用域和存储方式变量的作用域和存储方式5.6 函数间的数据传递函数间的数据传递5.7 指针函数指针函数5.8 函数指针函数指针要求掌握函数的概念和定义方法,理解实参和形参的一要求掌握函数的概念和定义方法,理解实参和形参的一致性致性(5.1-5.4)理解函数的执行过程,理解函数中的各种数据的

2、作用域理解函数的执行过程,理解函数中的各种数据的作用域和传递方法和传递方法(5.4-5.6)了解函数指针和指针函数的概念(了解函数指针和指针函数的概念(5.7-5.8)u学习内容学习内容 u学习目标学习目标 lC语语言是一种言是一种结结构化程序构化程序设计语设计语言,函数言,函数是其基本模是其基本模块块,当要解决的,当要解决的问题问题比比较较复复杂杂时时,可以把复,可以把复杂问题杂问题分解成若干个分解成若干个简单问简单问题题,每个,每个简单问题简单问题用用单单独的函数独的函数实现实现,通,通过过函数函数调调用用执执行某个功能,如此将一个复行某个功能,如此将一个复杂杂的程序分化,可使程序的的程序

3、分化,可使程序的结结构更构更为为清晰。清晰。5.1 C程序结构程序结构2023/4/274 程序结构清晰,可读性好。程序结构清晰,可读性好。程序结构清晰,可读性好。程序结构清晰,可读性好。减少重复编码的工作量。减少重复编码的工作量。减少重复编码的工作量。减少重复编码的工作量。可多人共同编制一个大程序,缩短程序设计周期,可多人共同编制一个大程序,缩短程序设计周期,可多人共同编制一个大程序,缩短程序设计周期,可多人共同编制一个大程序,缩短程序设计周期,提高程序设计和调试的效率。提高程序设计和调试的效率。提高程序设计和调试的效率。提高程序设计和调试的效率。使用函数使用函数使用函数使用函数的好处的好处

4、的好处的好处C程序程序源程序文件源程序文件n函数函数1函数函数m 源程序文件源程序文件1函数函数1函数函数n复杂问题的结构化程序设计思想:复杂问题的结构化程序设计思想:复杂问题的结构化程序设计思想:复杂问题的结构化程序设计思想:“自上而下,逐步细化,结构化,模块化自上而下,逐步细化,结构化,模块化自上而下,逐步细化,结构化,模块化自上而下,逐步细化,结构化,模块化”C C程序的一般结构程序的一般结构程序的一般结构程序的一般结构 案例一案例一 四则运算器四则运算器 l1.问题描述l计算器是一种很方便的小工具。参照算器是一种很方便的小工具。参照计算器算器进行行简单模模拟,实现针对两个整数的四两个整

5、数的四则运算。运算。l2.问题分析l本案例需要本案例需要实现加、减、乘、除四加、减、乘、除四则运算,其中加、减、乘三种运运算,其中加、减、乘三种运算算处理方法完全一致,除法因要考理方法完全一致,除法因要考虑除数不能除数不能为0的情况,略有不的情况,略有不同。同。因此此因此此处以乘法操作以乘法操作为例,例,对计算算过程程进行分析。行分析。l执行乘法操作的行乘法操作的细节如下:如下:l(1)乘法操作需要两个操作数,首先由用乘法操作需要两个操作数,首先由用户输入一个数据,作入一个数据,作为第第一个操作数;一个操作数;l(2)其次用其次用户输入一个操作符,此入一个操作符,此处应输入乘法符号;入乘法符号

6、;l(3)然后用然后用户输入第二个操作数;入第二个操作数;l(4)最后用最后用户按下回按下回车符,将数据符,将数据传入入计算机内算机内进行行计算,算,计算器算器操作之后操作之后输出出结果。果。l除法运算与乘法运算也基本相同,只是在除法运算与乘法运算也基本相同,只是在输入第二个操作数入第二个操作数时,需,需要要进行判断,当第二个操作数不行判断,当第二个操作数不为0时才能才能继续往下往下执行。行。l3.C语言代码l#include lvoid Add(float op1,float op2)/*加法函数加法函数*/l float s;l s=op1+op2;l printf(%.2fn,s);ll

7、void Sub(float op1,float op2)/*减法函数减法函数*/ll float s;l s=op1-op2;l printf(%.2fn,s);llvoid Mult(float op1,float op2)/*乘法函数乘法函数*/ll float s;l s=op1*op2;l printf(%.2fn,s);llvoid Div(float op1,float op2)/*除法函数除法函数*/ll if(op2=0)l printf(除数不能除数不能为0!);l elsel l float s;/*复合复合语句中定句中定义的的块变量量*/l s=op1/op2;l pr

8、intf(%.2fn,s);l llvoid main()ll float op1,op2;/*定定义两个操作数两个操作数变量量*/l char ch;/*定定义一个运算符一个运算符*/l printf(请输入数据和四入数据和四则运算符运算符(+-*/),如:如:2+4n);l scanf(%f%c%f,&op1,&ch,&op2);l switch(ch)l l case+:Add(op1,op2);break;l case-:Sub(op1,op2);break;l case*:Mult(op1,op2);break;l case/:Div(op1,op2);break;l default

9、:break;l ll4.程序运行结果l请输入数据和四入数据和四则运算符运算符(+-*/),如:如:2+4l3*6l18.005.1 函数的基本概念和操作函数的基本概念和操作 l5.1.1 函数的概念lC语言是言是结构化程序构化程序设计语言,一个言,一个C语言程序由一个或言程序由一个或多个源程序文件多个源程序文件组成。成。这样可以分可以分别编写、分写、分别编译,提高提高调度效率。一个源程序文件由一个或多个函数度效率。一个源程序文件由一个或多个函数组成。成。一个源程序文件是一个一个源程序文件是一个编译单位。位。lC语言中的函数是一个独立完成某种功能的程序言中的函数是一个独立完成某种功能的程序块,

10、其,其中封装了一些程序代中封装了一些程序代码和数据。使用者只需关心函数的和数据。使用者只需关心函数的功能和使用方法,而不必关心函数功能的具体功能和使用方法,而不必关心函数功能的具体实现细节。利用函数可将复利用函数可将复杂问题的解决的解决过程分割成一个个小的模程分割成一个个小的模块,每一个模,每一个模块编写一个函数,而各函数分写一个函数,而各函数分别完成一个完成一个功能功能单一而独立的任一而独立的任务,因此,因此C语言程序通常是由言程序通常是由许多多函数函数组成。函数在使用之前除了成。函数在使用之前除了标准函数准函数库的函数以外,的函数以外,其他函数都必其他函数都必须事先定事先定义。l在在C语言

11、中,根据使用的角度不同,函数可以有以下的分言中,根据使用的角度不同,函数可以有以下的分类。l(1)从用从用户使用的角度,函数分使用的角度,函数分为两两类:标准函数和用准函数和用户自定自定义函函数。数。l标准函数:在准函数:在C语言的言的编译系系统中提供了很多系中提供了很多系统预定定义的函数,的函数,用用户程序只需包含有相程序只需包含有相应的的头文件就可以直接文件就可以直接调用,不同的用,不同的编译系系统提供的提供的库函数名称和功能是不完全相同的。例如在上一章所介函数名称和功能是不完全相同的。例如在上一章所介绍的字符串的字符串处理函数都是系理函数都是系统给我我们提供的提供的标准函数,只需要在使用

12、准函数,只需要在使用时将将头文件文件string.h包含包含进来就可以了。来就可以了。l用用户自定自定义函数:用函数:用户根据自己特殊需要,按照根据自己特殊需要,按照C语言的言的语法法规定定编写一段程序,写一段程序,实现特定的功能。特定的功能。l(2)从函数参数的形式,函数分从函数参数的形式,函数分为两两类:无参函数和有参函数。:无参函数和有参函数。l无参函数:使用无参函数:使用该类函数函数时,不需,不需给函数提供数据信息,就可以直函数提供数据信息,就可以直接使用接使用该函数提供的功能。函数提供的功能。l有参函数:使用有参函数:使用该类函数函数时,必,必须给该函数提供所需要的数据信息,函数提供

13、所需要的数据信息,按照提供的数据不同,在使用按照提供的数据不同,在使用该函数后函数后获得不同的得不同的结果。果。5.1.2 函数的定义l前面提到,从函数参数的形式角度来看,前面提到,从函数参数的形式角度来看,函数分函数分为无参函数和有参函数,下面分无参函数和有参函数,下面分别介介绍这两种函数的定两种函数的定义形式。形式。l1.无参函数的定义l无参函数定无参函数定义的一般形式的一般形式为l返回返回值类型型 函数名函数名()ll说明部分明部分l执行部分行部分ll说明:明:l(1)无参函数定无参函数定义由函数由函数头部和函数体两部分部和函数体两部分组成。函数成。函数头部包括部包括返回返回值类型,函数

14、名两个部分;在型,函数名两个部分;在内的部分称内的部分称为函数体,其在函数体,其在语法上是一个复合法上是一个复合语句。句。l(2)函数名是唯一函数名是唯一标识函数的名字,是函数的名字,是C语言中任何合法的言中任何合法的标识符,符,而且在而且在该标识符后面必符后面必须有一有一对圆括号,用来表明括号,用来表明该标识符符为函数函数名。名。l(3)返回返回值类型是在型是在调用函数用函数结束后,函数束后,函数给调用者返回用者返回结果所具果所具有的有的类型,返回型,返回值的的类型型为各种基本数据各种基本数据类型和自定型和自定义数据数据类型;型;函数在被函数在被调用后也可以没有返回用后也可以没有返回值,此,

15、此时返回返回值类型型为void;另外,;另外,函数默函数默认返回返回值类型型为int。例如:。例如:lvoid output()ll printf(*);ll注意:注意:l(1)函数体内可以是函数体内可以是0条、条、1条或多条条或多条语句。当函数体是句。当函数体是0条条语句句时,称,称该函函数数为空函数。空函数作空函数。空函数作为一种什么都不一种什么都不执行的函数,通常在程序行的函数,通常在程序设计初期初期作作为临时函数使用,在函数使用,在设计过程中再程中再实现或或扩充功能。注意函数体内无充功能。注意函数体内无论有多少条有多少条语句,大括号是不能省略的。例如:句,大括号是不能省略的。例如:lv

16、oid nothing()l ll(2)在函数体内不能定在函数体内不能定义另一个函数,也就是另一个函数,也就是说函数定函数定义不能嵌套。例如下不能嵌套。例如下面函数的定面函数的定义是是错误的。的。lvoid output1()ll printf(*);l void output2()l l printf(#);l ll2.有参函数的定义l有参函数定有参函数定义与无参函数的区与无参函数的区别在于有参函数在于有参函数带有参数表列,作用有参数表列,作用是在函数被是在函数被调用用时接受提供接受提供给该函数的数据,以便在函数体内函数的数据,以便在函数体内进行行处理。理。l有参函数定有参函数定义的一般形式

17、的一般形式为l返回返回值类型型 函数名函数名(参数表列参数表列)ll 说明部分明部分l 执行部分行部分ll说明:明:l(1)返回返回值、函数名和函数体与无参数含、函数名和函数体与无参数含义相同;相同;l(2)参数表列通常称参数表列通常称为形式参数表形式参数表(简称形参表称形参表),形式参数表的形式,形式参数表的形式为l类型型 参数名参数名1,类型型 参数名参数名2,.,类型型 参数名参数名nl其中,形参表其中,形参表说明函数参数的名称、明函数参数的名称、类型和数目,由一个或多个参型和数目,由一个或多个参数数说明明组成,每个参数成,每个参数说明之明之间用逗号分隔。用逗号分隔。书写函数写函数时要养

18、成要养成给函数注函数注释的的习惯,一般最少要,一般最少要对函数的功能,参数的意函数的功能,参数的意义进行行说明。明。l例如,例如,输输出两个整数出两个整数值值的函数可定的函数可定义为义为:lvoid outint(int x,int y)/*有参函数定有参函数定义义*/ll printf(x=%d,y=%d,x,y);ll3.函数的返回值与return语句l调用者在用者在调用函数用函数时,函数有,函数有时需要把需要把处理的理的结果返回果返回给调用者,用者,这个个结果就是函数的返回果就是函数的返回值,函数的返回,函数的返回值是由是由return语句句传递的。的。lreturn语句的形式:句的形式

19、:lreturn(表达式表达式);或;或 return表达式;或表达式;或 return;l注意:注意:l(1)return语句中表达式的句中表达式的类型型应与函数返回与函数返回值类型一致,若不一型一致,若不一致,致,则以函数返回以函数返回值的的类型型为准,准,对于数于数值型数据将自型数据将自动进行行类型型转换。void类型函数中型函数中return后不得跟表达式。后不得跟表达式。l(2)一个函数中可以有多个一个函数中可以有多个return语句,函数在碰到第一个句,函数在碰到第一个return语句返回,函数返回句返回,函数返回值为第一个第一个return语句中表达式的句中表达式的值;若;若re

20、turn后面无表达式,后面无表达式,则返回返回调用函数用函数处。l(3)若函数体内没有若函数体内没有return语句,就一直句,就一直执行到函数体的末尾后返回行到函数体的末尾后返回调用函数。用函数。这时会返回一个不确定的函数会返回一个不确定的函数值,若确,若确实不要求返回函不要求返回函数数值,则应将函数定将函数定义为void类型。型。l例如,求两个整数的最大者的函数可定例如,求两个整数的最大者的函数可定义义为为:lint max(int x,int y)ll if(xy)l return x;l else l return y;l5.1.3 函数的调用与函数说明函数的调用与函数说明 l函数在定

21、函数在定义之后并不能主之后并不能主动运行,必运行,必须通通过对函函数数调用才能用才能实现函数的功能。一个函数可以被其函数的功能。一个函数可以被其他函数多次他函数多次调用用(main函数不能被任何函数函数不能被任何函数调用用),调用函数的函数称用函数的函数称为主主调函数,被函数,被调用的函数用的函数称称为被被调函数。如果被函数。如果被调函数是有参函数,主函数是有参函数,主调函数在函数在调用用时将数据将数据传递给被被调函数,从而得到函数,从而得到所需要的所需要的处理理结果。果。l1.函数调用的形式l(1)无参函数无参函数调用形式用形式为l函数名函数名();l(2)有参函数有参函数调用形式用形式为l

22、函数名函数名(参数表参数表);l注意:注意:l(1)函数函数调用用语句中函数名与函数定句中函数名与函数定义的名字相同。的名字相同。l(2)有参函数有参函数调用用时参数表中列出的参数是参数表中列出的参数是实际参数参数(简称称实参参)。l实参的形式参的形式为l参数参数1,参数,参数2,参数,参数nl其中,各参数其中,各参数间用逗号隔开,用逗号隔开,实参与形参要保持参与形参要保持顺序一序一致、个数一致、致、个数一致、类型型应一致。一致。实参与形参按参与形参按顺序一一序一一对应,传递数据。当数据。当实参与形参参与形参类型不一致型不一致时,实参的参的值转化化为形参的形参的类型型赋给形参。形参。l(3)实

23、参要有确定的参要有确定的值,它可以是一个表达式或者是,它可以是一个表达式或者是值。例如:例如:lint y=3;loutput();/*无参函数无参函数调用用*/loutint(2,y);/*有参函数有参函数调用用*/l2.函数调用的使用方式l(1)函数函数调用作用作为一个一个语句,函数完成一定功能。句,函数完成一定功能。例如:例如:lputchar(c);l(2)函数函数调用出用出现在表达式中,在表达式中,这时要求被要求被调函函数必数必须带有返回有返回值,返回,返回值将参加表达式的运算。将参加表达式的运算。l例如求两个整数的最大者的函数例如求两个整数的最大者的函数int max(int x,

24、int y)可以有如下可以有如下调用:用:lm=2+max(5,6);l(3)函数函数调用作用作为函数的函数的实参。例如参。例如lMax=max(a,max(b,c);l3.函数说明l在函数在函数调用用过程中,若被程中,若被调函数函数(除函数返回除函数返回值类型型为int、char之外之外)的定的定义出出现在主在主调函数之后,函数之后,则在在调用用函数前函数前还必必须对该被被调函数函数进行原型行原型说明。明。l函数函数类型型说明的格式明的格式为l返回返回值类型型 函数名函数名(参数参数类型表型表);l说明:明:l(1)圆括号是函数的括号是函数的标志,不能省略,如果省略,就成志,不能省略,如果省

25、略,就成为一般一般变量的量的说明了。明了。l(2)参数参数类型表的形式与函数定型表的形式与函数定义的形参表相同,也可以的形参表相同,也可以只列出形参的只列出形参的类型名。型名。l(3)函数函数类型型说明明语句句应放在主放在主调函数函数体中的数据函数函数体中的数据说明位置或在主明位置或在主调函数前面。函数前面。l例例5.1 定定义一个函数,一个函数,suv函数功能函数功能为求两个浮点数的之和,并在求两个浮点数的之和,并在主函数中主函数中调用此函数。用此函数。l#include stdio.hlvoid main()ll float suv(float,float);/*对suv函数函数进行行说明

26、明*/l float x1,x2,x3;l printf(input x1,x2);l scanf(%f%f,&x1,&x2);l x3=suv(x1,x2);l printf(nsuv=%6.2f,x3);llfloat suv(float x,float y)ll printf(%f,%f,x,y);l return(x+y);ll注意:注意:l(1)如果被如果被调调函数定函数定义义出出现现在主在主调调函数定函数定义义之前之前时时,在主,在主调调函数中不必函数中不必对对被被调调函数函数进进行行类类型型说说明。明。l(2)当被当被调调函数的返回函数的返回值为值为int型或型或char型型时时

27、,在主,在主调调函数中不必函数中不必对对被被调调函数函数进进行原行原型型说说明,但是有些明,但是有些编译编译器器(例如例如Visual C、Boland C)要求即使被要求即使被调调函数的返回函数的返回值为值为int型或型或char型型时时,也要提前声明,所以尽,也要提前声明,所以尽量把被量把被调调用函数写在主用函数写在主调调函数之前。函数之前。l4.函数调用的执行过程l调用函数的用函数的过程分程分为如下几步:如下几步:l第一步,将第一步,将实参的参的值赋给形参。形参。实参和形参的关系如同参和形参的关系如同赋值表达式的右操作数与左操作数的关系,表达式的右操作数与左操作数的关系,对于基本于基本类

28、型的参数,如果型的参数,如果实参的参的类型与形参的型与形参的类型相同,型相同,则实参参直接直接赋值给形参;否形参;否则实参按形参的参按形参的类型型执行行类型型转换后再后再赋给形参。如果形参。如果实参是数参是数组名,因名,因为数数组名表示数名表示数组的起始地址,所以的起始地址,所以实参参传递的是数的是数组的起始地址,而的起始地址,而不是不是变量的量的值;l第二步,将程序第二步,将程序执行流程从主行流程从主调函数的函数的调用用语句句转到被到被调函数的定函数的定义部分,部分,执行被行被调函数的函数体;函数的函数体;l第三步,当第三步,当执行到被行到被调函数函数体的第一个函数函数体的第一个return

29、 语句句或者最右或者最右边的一个大花括号的一个大花括号时,程序,程序执行流程返回到主行流程返回到主调函数的函数的调用用语句。若句。若调用用语句是表达式的一部分,句是表达式的一部分,则应用函数的返回用函数的返回值参与表达式运算之后参与表达式运算之后继续向下向下执行;行;若若调用用语句是句是单独一条独一条语句句则直接直接继续向下向下执行。行。案例二案例二 阶乘之和阶乘之和 l1.问题描述l编写程序,写程序,计算算s=1!+2!+n!,其中,其中n的的值由由键盘输入。求和与求入。求和与求阶乘分乘分别用两个用两个函数来完成。函数来完成。l2.问题分析l本案例首先可以定本案例首先可以定义两个子函数:子函

30、数两个子函数:子函数sum()实现求和功能,子函数求和功能,子函数fact()实现求求阶乘功能;然后通乘功能;然后通过主函数主函数调用子函数用子函数sum(),子函数,子函数sum()调用子函数用子函数fact(),实现函数的嵌套函数的嵌套调用。用。l3.C语言代码l#includellong fact(int n)/*定定义子函数子函数fact求求阶乘乘*/l if(n=0|n=1)l return 1;l elsel return n*fact(n-1);lllong sum(int n)/*定定义子函数子函数sum求累加和求累加和*/ll long s=0;l for(int i=1;i

31、=n;i+)l s=s+fact(i);/*嵌套嵌套调用用*/l return s;llvoid main()l int n;l printf(请输入累加的入累加的项数:数:);l scanf(%d,&n);l printf(1!+2!+%d!=%ldn,n,sum(n);/*输出出调用函数用函数sum之后的和之后的和值*/ll4.程序运行结果l请输入累加的入累加的项数:数:4l1!+2!+4!=335.2 函数的嵌套调用和递归调用l在函数的在函数的调调用中,用中,经经常会用到两常会用到两类类特殊的特殊的调调用形式,它用形式,它们们分分别别是函数的嵌套是函数的嵌套调调用和用和递归调递归调用。用

32、。5.2.1 函数的嵌套调用l1.函数嵌套调用的定义l函数定函数定义部分不能嵌套,各个函数定部分不能嵌套,各个函数定义是相是相对独独立的,但是任何函数内部都可以立的,但是任何函数内部都可以调用另外一个非用另外一个非主函数主函数main()的函数。的函数。这样一个函数一个函数调用另一个用另一个函数,而另一个函数又可以函数,而另一个函数又可以调用其他的函数的用其他的函数的调用用过程,就形成了函数的嵌套程,就形成了函数的嵌套调用。用。l2.函数嵌套调用的过程l例如程序中有两个子函数,分例如程序中有两个子函数,分别是是f1和和f2,主函,主函数数main对f1函数函数进行行调用,用,f1函数又函数又对

33、f2函数函数进行行调用,用,这种情况成种情况成为函数的嵌套函数的嵌套调用,用,调用用过程描述如程描述如图5.1所示。所示。l说明:明:l要要实现函数的嵌套函数的嵌套调用,需要用,需要满足以下条件:足以下条件:l(1)至少有两个子函数;至少有两个子函数;l(2)子函数的函数体中有子函数的函数体中有对其他子函数的其他子函数的调用用语句。句。图5.1 函数的嵌套调用过程5.2.2 函数的递归调用l如果要用如果要用递归思想求解思想求解这个个问题,就需要学,就需要学习函函数数递归调用的相关知用的相关知识。l1函数递归调用的定义l在在调用一个函数的用一个函数的过程中如果出程中如果出现直接或直接或间接接调用

34、函数自身,即任何一个函数中用函数自身,即任何一个函数中调用自身的用自身的过程程称称为函数的函数的递归调用。用。C语言的特点之一就在于言的特点之一就在于允允许函数函数递归调用。用。l2函数递归调用的过程l根据根据调用的形式,函数用的形式,函数递归调用可以分用可以分为直接直接调用和用和间接接调用,其用,其执行行过程如程如图5.2和和图5.3所示。所示。图5.2 直接调用 图5.3 间接调用 l从从图5.2可以看出,在可以看出,在调用用f函数的函数的过程中又程中又调用用f函数,函数,这种种过程是直接程是直接递归调用。从用。从图5.3可以可以看出,在看出,在调用用f1函数的函数的过程中要程中要调用用f

35、2函数,而函数,而在在调用用f2函数函数过程中又要程中又要调用用f1函数,从而形成函数,从而形成了了间接接递归调用自身的函数用自身的函数调用用过程。程。l说明:从明:从递归函数的函数的执行行过程我程我们可以看到以上可以看到以上两种两种递归调用都是永用都是永远无法无法结束的自身束的自身调用,程用,程序中不序中不应存在存在这种无种无终止的止的递归调用,而只用,而只应出出现有限次数的,有有限次数的,有终止的止的递归调用。解决方法是用。解决方法是可利用可利用if语句来控制句来控制这样循循环调用自身的用自身的过程,程,将将递归调用用过程改程改为当某一条件成立当某一条件成立时才才执行行递归调用,否用,否则

36、就不再就不再执行行递归调用用过程。程。l例例5.2 歌德巴赫猜想:一个充分大的偶数歌德巴赫猜想:一个充分大的偶数(大于或等于大于或等于6)可以分解可以分解为为两个素数之和。两个素数之和。编编写程序,将写程序,将6至至50之之间间全部偶数表示全部偶数表示为为两个素数之和。两个素数之和。l分析:根据分析:根据问题问题描述,要将描述,要将6至至50之之间间的的偶数分解偶数分解为为两个整数,然后判断分解出的两个整数,然后判断分解出的两个整数是否均两个整数是否均为为素数。若是,素数。若是,则满则满足足题题意,否意,否则应则应重新重新进进行分解和判断。行分解和判断。l#include l#include

37、l#include lint isSushu(int i)l if(i2)return 0;/*最小素数是最小素数是2*/l for(int j=2;j=sqrt(i);j+)l l if(i%j=0)l return 0;/*如果不如果不是素数返回是素数返回0*/l l return 1;/*如果是如果是素数返回素数返回1*/l lvoid _func(int num)l l for(int i=3;i 50;i+)l l if(isSushu(i)/*如果如果i是是素数素数*/l l if(isSushu(num-i)/*如果如果num-i也是素数也是素数*/l l printf(%2d=

38、%2d+%2d ,num,i,(num-i);l break;l l l l lvoid main()ll int num;l int n=0;l for(num=6;num=50;num+=2)l l _func(num);/*将将num传递给函数传递给函数_func()*/l n+;l if(n%5=0)/*每行每行5个换行个换行*/l printf(n);l ll程序运行程序运行结果如下果如下:l6=3+3 8=3+5 10=3+7 12=5+7 14=3+11l16=3+13 18=5+13 20=3+17 22=3+19 24=5+19l26=3+23 28=5+23 30=7+23

39、 32=3+29 34=3+31l36=5+31 38=7+31 40=3+37 42=5+37 44=3+41l46=3+43 48=5+43 50=3+47 案例三案例三 值传递与地址传递值传递与地址传递 l1.问题描述l分析下面两个程序的执行结果有什么不同。l程序1:l#includelvoid change(int x,int y)/*交换x和y的值*/ll int temp;l temp=x;l x=y;l y=temp;l printf(x=%d,y=%dn,x,y);llvoid main()ll int a,b;l printf(input a,b:);l scanf(%d,%

40、d,&a,&b);l printf(a=%d,b=%dn,a,b);l change(a,b);l printf(a=%d,b=%dn,a,b);ll程序程序2:l#includelvoid change(int*x,int *y)/*交交换x和和y两个指两个指针指向的指向的值*/ll int temp;l temp=*x;l *x=*y;l *y=temp;l printf(x=%d,y=%dn,*x,*y);llvoid main()ll int a,b,*m,*n;l printf(input a,b:);l scanf(%d,%d,&a,&b);l printf(a=%d,b=%dn,

41、a,b);l m=&a;l n=&b;l change(m,n);l printf(a=%d,b=%dn,a,b);ll2.问题分析l要解决本例要解决本例问题,需要我,需要我们对下面几个下面几个问题进行分析:行分析:l(1)子函数的形参可以是什么子函数的形参可以是什么类型;型;l(2)当形参的当形参的类型型为数数值和和为指指针时有什么不同;有什么不同;l(3)当形参是指当形参是指针类型型时,实参参应该如何如何给形参。形参。l3.执行结果l程序程序1:linput a,b:2,3la=2,b=3lx=3,y=2la=2,b=3l程序程序2:linput a,b:2,3la=2,b=3lx=3,y

42、=2la=3,b=25.3 函数间数据传递函数间数据传递 l在函数在函数调调用用时时由主由主调调函数将函数将实实参的参的值传值传送送给给被被调调函数的形参,或者由被函数的形参,或者由被调调函数向主函数向主调调函数返回数据的函数返回数据的过过程都称程都称为为函数函数间间的数的数据据传递传递。按照。按照实实参参传递值传递值的的类类型型(即即实实参存参存储储的是的是值还值还是指是指针针),函数,函数间间数据数据传递传递分分为为两种方式:两种方式:传值传值方式和方式和传递传递地址方式。地址方式。5.3.1 传值方式传递数据l当当实参参为简单类型型变量或者数量或者数组元素元素时,实参的参的值在函在函数数

43、调用用时被被传递给形参,但形参的形参,但形参的值在函数返回在函数返回时不能不能传递给实参。因参。因为在内存中,在内存中,实参与形参是不同的存参与形参是不同的存储单元,在元,在调用函数用函数时给形参分配存形参分配存储单元,并将元,并将实参参对应的的值赋值给形参,由于形参是被形参,由于形参是被调函数中的局部函数中的局部动态变量,量,调用用结束后形参被束后形参被释放,放,实参仍然保留并参仍然保留并维持原持原值。所以。所以执行被行被调用函数用函数时,即使形参的,即使形参的值发生改生改变,但并不能但并不能够改改变主主调函数函数实参的参的值。l分析案例三中程序分析案例三中程序1,函数,函数change()

44、中形参中形参x和和y为简单类型型变量,所以当主函数量,所以当主函数调用它用它时参数参数传递方式方式为值传递方式,所以在方式,所以在调用函数用函数change()时,系,系统首先首先为形参形参x和和y分配相分配相应的存的存储单元,然后将元,然后将实参参a、b的的值传递给x、y,当,当执行行change()的函数体部分后,的函数体部分后,x和和y的的值互互换。函数函数执行完行完毕,形参,形参x和和y的存的存储单元被元被释放,其放,其值消失,消失,我我们看到主函数中看到主函数中实参参a和和b的存的存储单元仍保留原先的元仍保留原先的值。程序程序执行行过程中程中实参与形参的参与形参的变化化过程如程如图5

45、.65.8所所示示:l(1)主函数主函数调调用用change()函数函数(执执行行语语句句change(a,b)。图5.6 调用change()函数 l(2)程序流程程序流程转转到到change()函数函数执执行。行。图5.7 参数值传递l(3)change()函数函数调调用用结结束,返回主函数。束,返回主函数。图5.8 change()函数调用结束5.3.2 传地址方式传递数据传地址方式传递数据 l如果如果实参的参的值是指是指针类型,也就是一个数据的内型,也就是一个数据的内存地址,在将存地址,在将实参的参的值传递给形参形参时,被,被调函数函数形参所接受是形参所接受是这个数据的内存地址,个数据

46、的内存地址,则在函数内在函数内可以通可以通过地址改地址改变实参所指向的数据,参所指向的数据,这种种传递数据的方式称数据的方式称为传地址方式。地址方式。l分析案例三中程序分析案例三中程序2,这里函数里函数change()的形参的形参为指指针变量,在量,在调用此函数用此函数时参数参数传递属于地址属于地址传递方式,所以方式,所以调用函数用函数change()时传给函数函数形参的是指向主函数中形参的是指向主函数中变量量a、b的指的指针,即,即变量量a、b的地址,所以函数的地址,所以函数change()中的形参中的形参x和和y分分别存存储主函数中的主函数中的变量量a、b地址的指地址的指针。这样在函数在函

47、数change()中,就可以利用形参通中,就可以利用形参通过指指向运算来改向运算来改变主函数中主函数中变量量a、b的的值。l程序程序执执行行过过程中程中实实参与形参的参与形参的变变化化过过程如程如图图5.95.11所示:所示:l(1)主函数主函数调调用函数用函数change()(执执行行语语句句change(a,b)。图5.9 调用change()函数l(2)程序流程程序流程转转到函数到函数change()执执行。行。l步步骤骤1:在函数:在函数change()中通中通过过“*”运算运算访访问问主函数中主函数中实实参所指向的参所指向的变变量量a、b;图5.10 地址传递l步步骤骤2:在函数:在

48、函数change()中交中交换换主函数中主函数中实实参所指向的参所指向的变变量量a、b的的值值。图5.11 形参改变实参的值l数数组名作函数参数名作函数参数时,把,把实参数参数组a的起始地址的起始地址传递给形参数形参数组b,这样两个数两个数组就共占同一段就共占同一段内存内存单元。形参数元。形参数组中各元素中各元素值的的变化同化同样会使会使实参数参数组元素元素值发生生变化。如果形参是数化。如果形参是数组形式,形式,则实参可以是数参可以是数组名或指向数名或指向数组的指的指针,如果,如果实参是数参是数组名,名,则形参也可以是同形参也可以是同样类型的数型的数组名名或指或指针。l通通过这个例子我个例子我

49、们可以看出:如果我可以看出:如果我们需要改需要改变某个某个变量的量的值,不能,不能传递变量的量的值而要而要传递变量量的地址,即使的地址,即使这个个变量是指量是指针类型,也要型,也要传递指指针的地址,也就是多的地址,也就是多级指指针。注意。注意设计形参形参时要要和和实参参类型匹配,使用型匹配,使用类型一致的地址,才能改型一致的地址,才能改变实参的参的值。案例五 远水不救近火l1.问题描述l“远水不救近火水不救近火”意思是意思是远处的水救不了近的水救不了近处的火,的火,这是因是因为起火的地方已起火的地方已经超出了水的作用范超出了水的作用范围。假如有一。假如有一火警,需要用水扑火警,需要用水扑灭,有

50、,有远处的水,也有近的水,也有近处的水,如的水,如果果选择远处的水,的水,则火警无法解除,如果火警无法解除,如果选择近近处的水,的水,则火警解除。火警解除。l2.问题分析l在在C语言中,不同的言中,不同的变量也有量也有这不同的作用范不同的作用范围。将。将C语言中的言中的变量比作量比作“水水”和和“火火”,那么定,那么定义在不同代在不同代码中的中的变量也有量也有远近之分。本案例要求近之分。本案例要求实现代代码中不同位中不同位置置变量的定量的定义和使用。和使用。l要要实现上述案例,需要考上述案例,需要考虑如下几个如下几个问题:l(1)什么是什么是变量的作用域;量的作用域;l(2)变量的作用域如何量

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 应用文书 > 工作计划

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号© 2020-2023 www.taowenge.com 淘文阁