找回密码
 立即注册

微信扫码登录

使用验证码登录

搜索
查看: 75|回复: 0

15.第15节课第七章用函数实现模块化程序设计

[复制链接]

6476

主题

3

回帖

1万

积分

管理员

积分
19556
发表于 2024-4-15 08:49:22 | 显示全部楼层 |阅读模式
好同学们,大家好,今天呢,我们为大家讲解一下,我们用函数实现模块化程序设计的后面一部分内容。那么,我们之前讲过的呢,是函数的简单调用。在被调用的函数体当中呢,没有再调用其他函数,而在一些比较复杂的问题当中呢。往往要在调用一个函数的过程中又调用。另一个函数。好,我们来看一下函数的递归调用。

在一个。函数的调用过程中呢,又直接或间接的调用该函数本身。那么,称之为函数的递归调用。C语言,它的特点之一呢,就是允许函数的递归调用。那么,我们看这样一个例子in tfx in TF in tx。int yzz=fy retell 2×z。那么,我们可以看到。在执行f的函数的过程当中呢,又要调用f函数,

那么就是什么呢?可以看到,在调用f函数的过程中,又调用了f函数,这就是直接调用本函数。那么,这是直接调用本函数?那么,我们来看一下,这是我们的直接递归。那么,我们还有间接递归,比如说。如果在调用我们f1函数的过程中,又调用了f2函数,

而在调用f2函数的过程中呢?又要调用f1函数,那么就是间接调用本函数。在调用一个函数的过程中呢,调用另一个函数称为函数的嵌套调用。在调用一个函数过程中,直接或间接调用本函数了,称之为函数的递归调用。那么,我们从这两个例子当中呢?可以看到。这两种递归调用了。都是无终止的自身调用,显然程序中不应出现这种无终止的递归调用。而只因出现有限次数的有终止的递归调用。

例如。选择指定递归调用的次数或者指定当某一条件成立时才执行递归调用。当该条件不满足时,就不再继续。我们可以了用。if语句来实现控制,那么这样一种方式啊,出现有限次数的有终止的。递归调用。好,我们来看一下这样一个递归调用的例子,我们一起来分析一下。这个例子呢,是五个学生坐在一起。问,

第五个学生多少岁?他说,比第二个学生大两岁,问第那么就去问第四个学生多少岁了?他又说,比第三个学生大两岁。那么,接下来,接下来直一直问下去了,问到第一个学生的时候呢?他说是十岁,那么请问五个第五个学生多大?那么我们这个题的解题思路呢?是想知道求第五个学生的年龄。就必须知道了第四个学生的年龄。

而第四个学生的年龄呢,也不知道想要求第四个学生的年龄呢,必须先知道第三个学生的年龄。而第三个学生的年龄呢,又取决于第二个学生的年龄,第二个学生的年龄呢。取决于第一个学生的年龄,而且每一个学生的年龄呢,都比前一个学生呢。大两岁,显然这是一个递归问题。如果我们的age是年龄函数。a及n代表第n个学生的年龄,那么我们可以呢,用一些式子来进行表示这样一个关系。

比如说age 5=age四+2。age 4=age三+2,age 3=age二+2。age一二=2g1+2,age 1=10,我们可以呢,用一个数学公式来进行表示。那么,这个数学公式呢?就是a gen当n=1的时候呢?它是十当n大于一的时候呢?它等于a gen- 1+2。二那么可以看到当n呢大于一的时候呢,求第n个学生的年龄的公式呢,是相同的。

就是前一个学生的年龄加二,因此呢,可以用同一个公式呢表述。上述关系。那么我们可以呢,从这个思路当中,这个图当中呢,可以看到求解呢,分为两个阶段。第一个阶段呢,是回溯,那么就是记。将第n个学生的年龄呢表示为第n- 1个学生年龄的函数a及n- 1+2。而第n- 1个学生的年龄呢,仍然不知道还要回溯到了第n- 2个学生的年龄,

直到了。回溯到第一个学生的年龄,此时呢age已知不必再向前推进的这样一个部分。然后开始第二个阶段采用递推方法,从第一个学生的已知年龄呢,推算出第二个学生的年龄。从第二个学生的年龄呢,推算出第三个年龄,第三个学生的年龄一直推算出第五个学生的年龄位置,也就是说。一个递归问题呢,可以分为回溯和递推两个阶段,要经历若干步才能求出最后的值。那么这里呢?显而易见,

如果要求递归过程呢?不是无限制的进行下去。就必须呢,有一个结束递归过程的条件,比如说我们这个题当中这个例子当中age 1=10。就是我们递归结束的条件。那么,这就是我们递归问题的这样一个方式。好,我们来看一下我们编程的这样一个部分。编程呢,首先是int。main int age in tn,这是函数的这样一个声明。然后接下来呢,

是print函数,那么就是r0。我们的int age呢?in tn这个函数的定义呢?是in tci fn=1 c=10。else.c=a gen- 1+2 return c,那么这里呢?我们最开始呢?是对age函数的声明,然后呢,是我们的输出第五个学生年龄,我们定义递归函数呢。c作为存放函数返回值的变量,如果n=1,

这是递归的终止条件。如果n=1,那么年龄为十。返回我们的年龄的这样一个值,如果n不等于一,那么年龄呢?是前一个学生的年龄加二,那么这就是我们的递归的这样一个方式。那么,我们来看一下这个过程。我们的内函数当中呢?实际上呢?只有一个语句,整个问题的求解呢?全靠一个age 5函数调用来解决,

那么我们看一下这个函数的这样一个过程。A级函数呢,总共被调用五次,也就是A级5A级4A级3A级2A级一。其中呢,ag 5是main函数调用的,其余四次呢,是在ag函数中调用的。即调递归调,用了四次。我们呢,某一次调用age函数呢,并不是立即得到a gen的值,而是一次又一次的进行定位调用。到A级一时了才有确定的值,

然后在d推出A级2A级3A级4A级五。那么,这是我们递推的这样一个方式。首先呢,是我们的这样一个。进行一个递归递归的这样一个结束的条件呢,是n=1,然后呢,再进行递推。d推出后面的这样一个A级的,这样二三四五的值,这是我们递归的这样一个方式。那么我们再看一下函数的。递归调用。我们求阶乘的。

用递归的方法求n的阶乘。我们的这样一个。解题思路呢,我们可以首先呢,从一开始乘二再乘三。一直存到n。这种方法呢,容易理解也同也容易实现。但是呢,这与递归呢是不相同的。我们来看一下这个程序。int main int as function.in tn,这是我们function函数的声明,接下来in tn inty print play in put an integral numbers ff百分号d。

取n的地址,这样一个符号n将输入的数据呢?放在我们的变量n中,这是输入要求阶乘的。数接下来y等于方形n printf百分号d。感叹号等于百分号d返学号n NY return 0。我们来看一下这个递归函数,这个递归函数,这个递归函数int function in tn,这是定义function函数in tfifn小于零。printf n小于0 data error else。if.n=0。或者n=1。那么,

另将一呢赋给f,这是我们的递归终止条件。也就是说,当n=0或者。一的时候呢n的阶乘呢等于一。lf等于方形n,这是当n大于一的时候呢。n的阶乘呢?等于n乘以。n- 1的阶乘,最后呢r返回f的值那么?这是我们的递归的这样一个方式,我们来看一下。function函数呢,是用连乘的方法求n。

我们这样一个递归的解题思路呢?是并不是先求一神二再神三,一直神到n,而是直接从目标出发,提出问题。现在呢,我们比如说要求。比如说我们要求。方形五那么怎么样呢?才能得到五的阶乘呢?如果知道四的阶乘就能够通过四的阶乘乘五得到五的阶乘。而四的阶乘呢,也不知道要求出三的阶乘就能通过三的阶乘乘四。得到四的阶乘,而三的阶乘也不知道,

要知道二的阶乘才能通过二的阶乘使用三得到三的阶乘。而二的阶乘呢?等于一的阶乘乘二,而一的阶乘呢?是已知不必再回溯了,那么我们就可以用这样的公式n的阶乘。等于n。乘以n- 1的阶乘,这是当n大于一的时候,当n=0或一的时候呢?n的阶乘呢等于一,那么这就是。有了这样一个部分呢,我们就可以写出我们的这样一个递归的。函数。

那么,我们来看一下,比如说假如输入的值n值为五,在主调函数中,主函数中调用函数方形五就能求出五的阶乘。在执行function 5的过程中呢,由于五不等于零和一,所以执行f function n- 1。乘以n也就是说,四×5。需要递归调用function函数去调用function 4,在执行function 4的过程中呢,如果四不等于由于呢,四不等于零和一。那么这个时候呢,

需要执行方形。n- 1×n。由于此时n=4,所以相当于function 3×4。在执行function 3的过程中呢,由于三不等于零和一,所以执行f function n- 1×n。由于此时呢n=3。所以相当于f方形二×3在执行f方形二的过程中呢,由于二不等于零和一,所以执行f方形n- 1×n。由于此时n=2,所以相当于呢?function 1×2在执行function 1的过程中呢?由于一=1,

所以执行f1=1,不再递归调用function函数。所以呢,我们的递归调用呢,在这里呢,那么就。不再继续就就结束这样一个就结束,现在呢,是执行function 1的过程中。在执行完f=1的后面呢,就执行return语句f的值是一就。是函数f方一一的值return语句呢?将f的值一呢?带回f=function一×2中。此时的方格形一已经结束了,

现在执行方格形二的过程中呢?求出f等于方格形一,省二=2,然后执行方retard语句。将f2的f的值二呢?作为方形二的值了,带回方形三中f等于方形二×3。得到方形呢,二=2再乘以三=6r语句呢将f。的值六作为function 3的函数了,返回到function 4中。的f等于方a三三×4,那么得到了f=24 retire语句呢?再将f。四再加24作为方形四的值呢?

返回到方形五中的f等于方形四乘以乘以五中。求出f=24×5=120,由于f5呢是main函数调用的,所以呢,retire语句将120作为方形五的值了。返回内函数中的y=fa function n中,也就说y的值啊,等于function 5=120,所以说程序呢,输出120。那么,这是对递归调用的这样一个运用的过程,那么大家要注意一定要弄清楚,当前是处于哪一层的放射性函数过程中。求出的f值呢?

返回到哪一层的放行函数那么大家要注意这样一个部分。那么,从这样一个例子看中呢?我们可以看到递归调用的特点。从一个未知的结果f方形五出发,倒推回上一级的方形四。那么,希望通过方程四呢来求出方程五,但现在呢?方程四也是未知的,就再往回。推到上一层的方形三仍是未知的,就再向前推,那么一直呢,遇到推到我们的方形一,

那么现在方形一是已知的了,那么方形一=1。那么不用再推,不用再推了,不用再推,那么这是我们递归的边界条件,递归的这样一个出口。然后呢,继位的这样一个结束部分,然后呢,开始递推的过程有已知的条件呢f方形一推出方形二,再有已知的方形二推出方形三。由已知的方和弦三呢推出。方和弦四由已知的方和弦四呢推出。方和弦五最后得到最后的这样一个结果。

那么,这个是执行未知,推到未知,一直到我们的递归边界条件,然后执行已知向推,推向已推,推推到已知的这样一个过程。那么,这就是我们的递归的问题。那么,在这些递归的过程当中呢?大家要注意注意几个条件。第一个呢,是所缺九的问所求解的问题呢,能否?

转换为用同一方法解决了问题。第二个。子问题的规模比原问题的规模小。第三个必须要有递归结束的边界条件,也就说递归结束的条件。这是采用递归方法解题的这样一个条件,那么大家要注意这三个条件,第一个呢,是所求解问题能否转换为用同一方法解决的子问题。第二个子问题的规模呢?要比原问题的规模小,第三个必须要有递归结束条件,那么这是我们。一个问题呢,能否用递归方法解决那么这样一个要满足的这样一个取决的这样一个条件部分,

那么这是我们递归的这样一个方法。那么,接下来我们看一下函数组,作为函数参数的这样一个部分。前面呢,我们已经讲过了,变量作为函数参数,那么显然呢,数组元素呢,也可以作为函数实参。那么,其用法呢?与变量相同,另外呢?数组名呢?

也可以作为实参和形参传递的呢?是数组首元素的地址。那么,我们来看一下。形形参呢,可以是我是我们的变量,实参呢,可以是变量常量表达式数组元素,形参呢,可以是数组,那么实参呢,也可以是数组。数组元素可以作为函数实参,但是呢,不能作为形参,

因为形参呢,是在函数被调用时,临时分配存储单元的。不能为一个数组元素呢,单独分配存储单元数组是一个整体,在内存中呢,占连续的一串存储单元。再用数组元素做函数实参时,把实参的值呢传递给形参,是值传递的方式数据传递的方向呢?是从实参传到形参单向传递。我们来看一下用数组元素,那么作为时参作为函数时参的这样一个部分。输入十个数,要求呢,

输出其中最大的元素和该数是第几个数?我们假设呢,从键盘输入十个数,给a0到a9变量m,用来存放当前已经比较过的个数中的最大者。开始时呢m的值设为AA 0,然后呢依次将m与AI比较,如果AI大于m就以AI的取值。代替m的原值,下一次以m的新值与下一个AI比较,经过九轮循环的比较,呢m最后的值啊就是十个数的最大值,我们来看一下这个程序。int类,int max int xintyin ta 10 m ni。

printf enter ten in teg lumbers for I=0,这是我们的初始条件。I等小于十,这是我们循环循环条件表循环条。循环条件表达式,这是我们的循环的条件,部分I加加,这是我们变量的改变,部分就是我们变量的增量。输入十个数,给a0到a 9+f百分号d,那么这样一个符号AI将我们的这样一个输入的数据呢?放在我们的数组元数组当中。数组元素当中。printf反星in for I等于零一m=a零。

n=0 I小于10I加加,我们初始条件呢?是I=1 m=a零。n=0,这是我们的初始条件。if max m。AI大于m。那么m=max mai。n=I,这是如果max函数返回的这样一个值呢?大于m,那么就把max返回的值呢?取代m元值,然后把这样一个数组元素的序号记下来,放在n中,

接下来printf the largest number is百分号d反序根nis is the。百分号d。th number返回个n mn+1。那么。我们的int max函数呢?它的定义呢?是我们的retell x大于y问号x冒号y。这是我们max函数的定义,它的作用呢?是返回x和y中的最大值。那么,这就是我们数组元素作为函数实参的部分,那么大家看一下我们的这样一个max调,用我们max当中。我们max当中呢,

是用的是max它的这样一个。参数这样一个值的传递呢?我们用的是AI这个数组元素的部分,那么数组元素呢?它是作为我们函数的实参。来进行这样一个值的,这样一个传递,将实参的值呢传递给我们的形参,那么这是数组元素呢?作为函数实参的这样一个部分。那么我们再来看一下一维数组名,作为函数参数。那么用有一个一维数组scope内放十个学生,成绩求平均成绩。用数组元素呢,

作为实参的时候呢,向形参变量传递的呢,是数组元素的值,而用数组名做函数实参时。向形参传递的呢,是数组首元素的这样一个地址,那么我们来看一下程序。inter main float average float green array 10,那么这是我们的数组名。那么,作为我们那么这是我用我们的一我们的数组呢?作为我们的形参那么这是我们函数的这样一个声明。接下来float score 10 average那么定义一个浮点型数组,那么有十个元素再定义一个浮点型变量average。inti printf input ten scores for I=0 I小于10I加加sky f百分号f。

这样一个取地址符,这样一个符号score I将我们输入的数据呢?放在我们的数组元素中printf反斜杠nr。average=average score调用average函数,接下来printf average score is百分号五点二f返程I average。这里的五点二f呢表示,我们输入的数据长度呢是五。五位其中的小数部分呢,占了两位,最后return 0返回一个零值函函数及程序结束,我们看一下我们定义的average函数。float average.十那么定义函数I=0。float I=1 I小于10I加,加sun=sun+ivi,

累加学生成绩average=sun除,以10 return average。这里呢,我们用数组名呢,我们这样一个调用的函数呢,是average调用这个函数函数的时差是school,那么它是一个数组名。用这样一个数组名呢,它使用的呢,就是我们函数成用,用的是我们数组元首元素的地址,那么传递给了我们的这样一个形参,这样一个数组的这样一个部分。向形参呢传递的呢,是我们数组首元素的地址,

那就是我们这样一个用一维数组名呢,做函数参数的这样一个方式。用数组名做函数参数,应该在主调函数和被调函数分别定义数组。实参数组呢?与形参数组的类型必须一致,在定义average函数时,声明形参数组的大小为十。但实际上呢,指定其大小呢,是不起任何作用的,因为C语言编译系统呢,并不检查形参数组大小。只是将实参数组的首元素的地址呢,传递给形参数组名。

形参数组呢,这里大家注意形参数组可以不指定大小,在定义数组时呢,在数组名后呢,跟一个空的方括号,那么就可以了,我们可以了,不指定。定参数组的这样一个大小。


您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|5432考试网 ( 蜀ICP备2022024372号|川公网安备51152402000101号 )|网站地图

GMT+8, 2024-5-19 16:51 , Processed in 0.077762 second(s), 22 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表