资源预览内容
第1页 / 共39页
第2页 / 共39页
第3页 / 共39页
第4页 / 共39页
第5页 / 共39页
第6页 / 共39页
第7页 / 共39页
第8页 / 共39页
第9页 / 共39页
第10页 / 共39页
亲,该文档总共39页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述
,8.1 概述 8.2 函数定义的一般形式 8.3 函数参数和函数的值 8.4 函数的调用 8.5 函数的嵌套调用 8.6 函数的递归调用 8.7 数组作为函数的参数 8.8 局部变量和全局变量 8.9 变量的存储类别 8.10 内部函数和外部函数,结 束,8.1 概述,1.一个较大的程序一般应分为若干个程序模块,每一个模块用来完成一个特定的功能。这样做的优点是:a)每个模块要实现的功能相对简单,算法容易建立,程序的编写调试简单且不易出错;b)便于众多设计人员分工协作,发挥各自优势,提高软件的设计质量;c)减少重复设计。这就是所谓的“模块化程序设计”。 2.在C语言中,是用函数实现各个模块的功能。故,在C程序设计中,要实现模块化程序设计,一般要按照结构化程序设计方法,对给定的设计任务采用“自顶向下,逐步细化,模块化设计,结构化编码”的方法进行。 问题:1)众多函数如何编辑;2)众多函数之间的关系如何?3)如何建立一个函数?4) 怎样使用这些函数?,Back,Continue,Back,Continue,3.一个C程序由一个主函数和若干函数构成,这些函数可以分别编辑在不同的C语言源文件(.C)中。如下图所示。,4.一个C语言源程序由一个或多个函数及其它部分构成,但主函数只能存在于一个源程序文件中。一个函数由函数首部和函数体两部分构成。如下图所示。,Back,Continue,5. 函数的使用。不论所有函数是否处于同一源程序文件,均是主函数(main函数)调用其它函数,其它函数也可以相互调用,甚至一个函数也可以调用它自己,一个函数可以被一个或多个函数调用任意多次。如下图所示。,Back,Continue,6. 本章的主要任务1)学习并掌握函数的定义方法;2)学习并掌握函数的调用方法和调用形式;3)学习并掌握主调函数与被调函数之间的数据传递途径和实现方法。 7.说明:1)上述内容是我们利用C语言进行程序设计的关键或核心内容之一。当然,要在程序设计中真正发挥和体现C语言的优势及其特点,除了要掌握好本章所学的内容外,还有之后其他章节的内容。2)在定义一个函数时,在明确其功能的前提下,一定要注意以下三个方面的问题:有无需要加工的数据,如有,是什么样的数据;进行怎样的加工及如何加工;有无结果,如有,是什么样的数据(称为函数的返回值)。如下图所示。,Back,Continue,例如:求两个数中最大值的函数。int max(int a, int b)int c;c=ab?a:b;return (c);,由此例可以看出,所需加工的数据仅是一些符号量,具体的值并没有给定;而所进行的加工由C语言运算符表示,运算对象即为需要加工的数据a、b;加工的结果存放在变量c中。当该函数被调用后,a、b的具体值才可确定,结果也是一个确定的数值,给定不同的数据就可得到不同的结果。可见,定义一个函数,首先要根据要实现的功能要求,定义几个符号变量,再用C语言的运算符、表达式和语句描述出对它们所进行的一系列操作,并将结果存放起来,置于return后面即可。3)C语言系统提供了许多函数,对这些函数的理解与应用与上面的分析相同,在使用时我们需要知道它的功能(无需直到该功能是如何实现的),函数参数(即需加工的数据),返回值(即加工结果)。其实,,Back,Continue,当定义好一个函数后,对它的使用与系统提供的函数的使用方法相同。不过用户定义的函数形式更为丰富多样。,8.2 函数定义的一般形式,一、无参函数的定义类型标识符 函数名( ) 声明部分语句 二、有参函数的定义类型标识符 函数名(形式参数表列) 声明部分语句 如求两个数中最大值得函数和三个数中最大值的函数。int max(int a, int b,int c)int d;d=ab?a:b; d=cd?c:d;return (d);,Back,Continue,特点:不需要从外界获取数据(信息),其功能一般是完成一系列特定的操作,如输出,可以有、也没有返回值。类似于getchar( )、gets( )等。,Back,Continue,特点:这种类型的函数是最常见的用户自定义函数,需要从外界获得数据(函数参数),并对它们进行一系列操作获得所需的结果,作为函数的返回值。而且函数参数的数量及其类型任意,返回值的类型也是任意的。 三、“空函数”的定义类型说明符 函数名( ) 例如:dummy( ) 这种函数的函数体是空的,且没有参数,故称为“空函数”。调用此函数时什么工作也不做,没有任何实际作用。 这实际上是“结构化程序设计方法”在程序编写与编辑阶段的一种延续,即“自顶向下”:先定义好该源程序文件中包含的各个函数的头部(函数的类型和函数名),由于函数名往往具有“见名思意”的作用,这样使得一看到这些空函数,就能对该源文件中的所有函数及其功能有一个基本的了解,不致于遗漏;“逐步细化”:按每个函数的功能再逐个编写和完善,由于“空函数”是合法的,因此,每当编写完一个函数后,就可进行编译,,Back,Continue,若有错误,必定在该函数中,一般,每个函数中的语句较少,功能和算法相对简单,即使有错误,也很容易查找和修改。 四、对形参声明的传统方式,8.3 函数参数和函数的值,一、形式参数和实际参数 1. 形式参数:简称形参,定义函数时,函数名后括弧中的参数称为形式参数。它们只是一种符号量,没有具体的数值,也不占据存储单元,但必须指定其类型。 实际参数:简称实参,在主调函数中调用一个函数时,函数名后括弧中的参数(可以是常量或表达式)称为实际参数。它们具有确切的数值和类型,若是变量,还要占据存储单元。 3. 形参与实参间有数据的传递:当一个函数被调用后,首先要将实参的数据传递给对应的形参,接下来,程序的执行就转移到该函数,并对形参的进行一系列操作,操作结果(即函数的返回值)经由函数名返回到函数调用所在处。如例8.2中对max函数的调用。显然,值的传递是单向的。,Back,Continue,Back,Continue,4.由于实参与形参之间有值的传递,因此,两者的类型应相同或赋值兼容,若实参为常量或表达式,则其值的类型应与形参的类型相同或赋值兼容。 5.只有当一个函数被调用时,才给形参分配存储单元,一旦调用结束,形参所占用的内存空间就被释放。 二、函数的返回值希望通过函数调用使主调函数能得到一个确定的值,这个值就是函数的返回值。 1.函数的返回值是通过函数中的return语句获得的。Return语句的格式为:return(表达式); 或 return 表达式; 2.函数值得类型,即函数的类型,在定义时说明。 3.一般,函数的类型应与return语句后表达式的类型一致,若不一致,则以函数的类型为准,作自动类型转换。例8.3,Back,Continue,4.定义函数时,函数体中可以没有return语句,这并不意味着函数没有返回值,只是不返回一个确定的、用户所希望的函数值,返回的是一个不确定的数值。 5.为了明确表示一个函数“不返回值”,用“void”将函数定义为“无类型”或“空类型”。,8.4 函数的调用,一、调用的一般形式函数名(实参表列) 1. 实参与形参必须一一对应。 2. 实参可以是常量、赋了值的变量及可求的值的表达式。 2. 实参的求值顺序,许多C版本按自右向左的顺序求值。例8.4 二、函数的调用方式 1. 函数调用语句:不要求函数带回值,只要求函数完成一定的操作。 2. 函数表达式:函数的调用出现在表达式中,这时要求该函数带回一个确定的值参与表达式运算。 3. 函数参数:一个函数的调用作为调用另一个函数时的实参。如mmax(a, max(b, c) ;printf(“%d”,max(b,c);实质上也是以函数表达式形式出现的。,Back,Continue,Back,Continue,三、对被调用函数的说明和函数原型在一个函数中调用另一个函数(即被调函数)需要具备的条件:1. 被调用的函数必须是一个已经存在的函数(是库函数或用户自定义的函数)。2. 如果是库函数,还应在源文件的开头用include命令将调用有关库函数时需要的信息“包含”到本文件中。如#include #include 3. 如果调用的是用户自定义的函数,且该函数与调用它的函数(主调函数)在同一个文件中,一般还应该在主调函数中对被调函数作声明。例8.5 对北调用函数作声明。4. 对被调函数声明的格式类型标识符 函数名(形参表列);关于形参表列有三种情况:1)形参类型名 形参变量名 2)只有形参类型名 3)全无(但不作全面检查)5. 几种特殊情况,Back,Continue,1)如被调函数定义在主调函数之前,则在主调函数中可以不对被调函数作声明;2)在一个源文件中,若在所有函数定义之前,在主调函数的外部已作了函数的声明,则在各个主调函数中不必再对要调用的函数作声明;3)如果函数的类型为整型或字符型,则不论这类函数与主调函数的位置如何,可以不在主调函数中对它们做声明。,8.5 函数的嵌套调用,一、函数的嵌套调用C语言中的函数定义都是平行、独立的,即在定义函数时,一个函数内不能包含另一个函数,但在调用一个函数的过程中,该函数又可调用其它函数,甚至调用它自己,称前一种调用为函数的嵌套调用,后一种为函数的递归调用。如下图所示。,Back,Continue,Back,Continue,二、嵌套调用举例例8.6 用弦截法求方程x3-5x2+16x-80=0的根。,弦截法的思想设方程的一个解为x*,且在x*的有限邻域内,f(x)为单调函数。 A)给出分处于x*两侧的两个点x1、x2,计算出它们对应的函数值y1=f(x1),y2=f(x2) B)如|x1-x2|,则 x*=(x1+x2)/2,结束;否则,过点(x1,y1)和(x2,y2)作曲线的弦,求出弦于x轴的交点: x (x1*y2-x2*y1)/(y2-y1),并计算出:y=f(x) C)如y1*y0,则使:x1=x;y1=y;否则,使:x2=x;y2=yx; D)重复B)步和C)步。 【算法】,Back,Continue,从该算法的N-S流程图可见,要求出给定方程的根,必须解决好下面几个问题:,Back,Continue,1.函数f(x)=x3-5x2+16x-80值的计算。由于在多处存在这种计算,一般在程序设计中将这种运算用一个C语言中的函数实现。显然,该函数需要从外界获取一个数据(即题中所给函数的自变量),并具有函数值,且其类型应为实型。函数名标记为:f。 2.弦与x轴的交点x的计算。基于同样的原因,一般在程序设计中将这种运算也用一个C语言中的函数实现。显然,该函数需要从外界获取两个数据(即x1和x2),并应具有函数值(即弦与x轴的交点x ),且其类型应为实型。函数名标记为:xpoint。另外,在用xpoint函数计算交点x时,要先计算出x1和x2的函数值,故在xpoint中要调用f函数,显然为函数的嵌套调用。 3.方程f(x)=0的根的求解。只要采用弦截法求一元方程的根,不论f(x)的函数形式如何,求解算法是完全相同的。针对这种情况,在程序设计中,为了减少程序代码的重复编写,提高复用率和程序质量,往往也将该类运算用一个或几个C语言函数实现。显然,该需要从外界获取两个数据(即满足弦截法求解的x1和x2),并具有函数值(即方程f(x)=0的根),且其类型应为实型。函数名标记为:root。,Back,Continue,另外,在用root函数求解方程的根时,要计算弦与x轴的交点x,故在root中要调用xpoint函数,而在xpoint中又要调用f函数,显然为函数的嵌套调用。它们之间的调用关系如下图所示。,8.6 函数的递归调用,一、递归调用的功能、形式及其特点在调用一个函数的过程中,又程序直接或间接地调用该函数本身,称这种调用形式为函数的递归调用。 1. 直接递归调用,
网站客服QQ:2055934822
金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号