




已阅读5页,还剩34页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
函数与指针,第7章,7.1 概述,第7章,1按功能划分模块 划分模块的基本原则是:各模块都要易于理解,功能尽量单一,模块间的联系尽量少。满足这些要求的模块具有以下优点:,7.1.1 模块化程序结构的概念,(1)模块间的接口关系简单,这种程序可读性和可理解性较强。 (2)需要修改某一功能时,只涉及到一个模块,不会影响到其它模块。 (3)脱离程序的上、下文也能单独验证一个模块的正确性。 (4)扩充或建立新系统时,可充分利用已有的模块。,7.1 概述,第7章,2.按层次组织模块 结构化程序设计方法要求在设计程序时,按层次结构组织各模块。在按层次组织模块时,上层模块只需指出“做什么”,最底层的模块才精确地描述“怎么做”。例如,图7-1所示的层次结构中,主模块指出总任务;模块1、模块2、模块3分别指出各自的子任务;模块4、模块5、模块6才去精确描述“怎么做”。,7.1.1 模块化程序结构的概念,图 7-1 按层次调用模块,7.1 概述,第7章,【例7.1】简单的函数调用。 # include main( ) /* 主函数*/ p1( ); /* 调用p1函数*/ P2( ); /*调用p2函数*/ P1( ); /*再次调用p1函数*/ P1( ) /* 函数p1打印一行*号*/ printf(“* * * * * * * * * * * * * n”); P2( ) /*函数p2打印一行文字*/ printf(“ Welcome to C!n”); ,7.1.2 C语言程序的构成,运行结果为: * * * * * * * * * * * * * Welcome to C! * * * * * * * * * * * * *,7.2 函数的定义,第7章,1C语言函数的概念 函数就是用来完成一定的功能。所谓函数名就是给该功能起一个名字。如果该功能用来实现数学运算的,就是数学函数。在C语言中,往往把程序需要实现的一些功能分别编写为若干个函数,然后把它们组合成一个完整的程序。,7.2.1 C语言函数的概念及分类,7.2 函数的定义,第7章,2C语言函数的分类 (1)从用户使用的角度分类: 库函数。它是由编译系统提供的,用户不必定义可以直接使用的函数。 用户自定义函数。用户用来实现某种功能,本章主要学习自定义函数的编写与应用。 (2)从函数完成的任务分类: 有返回值函数。该类函数在结束时,将计算结果返回到主调函数。 无返回值函数。该类函数运行结束时,没有数据返回,它只是完成某一种操作。,7.2.1 C语言函数的概念及分类,7.2 函数的定义,第7章,(3)从函数的表示形式来分类: 无参函数。 主调函数没有将数据传递给被调函数,一般用来完成某一操作。无参函数可以带回或不带回函数值到主调函数。 有参函数。 调用该类函数时,在主调函数和被调函数之间有数据传递。主调函数可以将数据传递给被调函数使用,被调函数的计算结果也可以带回主调函数使用。,7.2.1 C语言函数的概念及分类,7.2 函数的定义,第7章,1.无参函数定义的一般形式,7.2.2 函数定义的一般形式,类型 函数名() 说明部分; 语句 ,7.2 函数的定义,第7章,2.有参函数定义的一般形式,7.2.2 函数定义的一般形式,类型 函数名(类型1 形参1,类型2 形参2,类型n 形参n) 说明部分; 语句部分; ,7.2 函数的定义,第7章,3. 定义空函数 在程序设计中有时会用到空函数,它的形式为:,7.2.2 函数定义的一般形式,类型 函数名() ;,7.3 函数的参数和函数的值,第7章,在调用函数时,大多数情况下,主调函数和被调函数之间有数据传递关系。这就是前面提到的有参函数。在定义函数时,函数名后面的括号中的变量称为“形式参数”,简称“形参”。在调用函数时,主调函数名后面括号中的参数(也可以是一个表达式)称为“实际参数”,简称“实参”。,7.3.1 形式参数和实际参数,7.3 函数的参数和函数的值,第7章,通过函数调用使主调函数得到一个值,这就是函数的返回值。函数的返回值是通过return语句来获得的,其格式为: return (返回值表达式); 或: return 返回值表达式 ; 功能:自定义函数运行结束,退出该函数,将“返回表达式”的值带给调用函数。,7.3.2 函数的返回值,7.3 函数的参数和函数的值,第7章,【例7.2】用函数求两个整数的最大值。 程序代码: #include main( ) /*主调函数main*/ int a, b, c; scanf(“%d, %d”, /*退出max函数,将变量z的值8返回给主调函数main*/ ,7.3.2 函数的返回值,运行结果: 7,8 max is 8,7.4 函数的调用,第7章,1调用库函数 调用库函数时,通常在文件开头用#include命令将调用有关库函数时所需用的信息“包含”到本文件中来。如:标准输入输出库函数用#include ,数学库函数用#include 。 2调用自定义函数 调用自定义函数,而且该函数与调用它的函数在同一个文件中,应在主调函数中对被调函数作声明(说明函数类型、参数类型及个数),以便编译系统对函数调用进行语法检查。,7.4.1 函数的原型与声明,7.4 函数的调用,第7章,格式:函数名(实参表列) 函数调用的执行过程: 先计算每个实参表达式的值,再赋值给所对应的形参中,然后执行被调用函数体,执行完函数后,返回到调用此函数的下一条语句,继续去执行主调程序中下面的语句。 说明: (1)如果是无参函数,则没有实参列表,但括弧不能省略。 (2)如果实参表列包含多个实参,则各参数间用逗号隔开。实参与形参的个数应相等,类型应一致。实参与形参是按顺序一一对应传递数据。,7.4.2 函数调用的一般形式,7.4 函数的调用,第7章,根据函数在程序中出现的位置,大致有3种调用方式: (1)函数语句 把函数调用作为一个语句。如: p1();这种调用不返回函数值,只要求函数完成一定的操作,如【例7.1】。 (2)函数表达式 函数出现在一个表达式中,这时要求函数带回一个确定的值以参加表达式的运算。如:x=2*max(a,b); (3)函数参数 一个函数作为另一个函数的实参。,7.4.3 函数的调用方式,7.5 函数的嵌套调用,第7章,C 语言定义的函数都是互相独立的,函数间不能嵌套定义(嵌套定义是指定义一个函数时,其函数体内包含另一个函数的完整定义),但可以嵌套调用,也就是说在调用一个函数的过程中,该函数又调用另一函数。 例如:f1 和f2是分别定义的函数,但在调用函数f1的过程中又要调用函数f2。其调用过程如图7-4所示:,图7-4 函数嵌套调用过程,7.6 函数的递归调用,第7章,在调用一个函数的过程中,又直接或间接地调用函数本身,称为函数的递归调用。 语言提供两种形式的递归调用: 直接递归调用:指函数直接调用函数本身的形式,其执行过程如图7-5所示。 间接递归调用:指函数调用其它函数,其它函数又调用原函数的形式, 其执行过程如图7-6所示。,图7-5 直接递归调用 图7-6 间接递归调用,7.6 函数的递归调用,第7章,递归调用的过程可以分为两个阶段: 一是从未知的向已知方向推测; 二是从已知的再向未知方向回推。在有限递归的情况下,总会有一个递归的结束条件。 递归函数的典型例子是求阶乘。下面通过求阶乘的函数,详细分析递归过程。阶乘的计算公式为: n!=n*(n-1)*2*1 递归的方法是逆推,即n!等于n.(n-1)!, 而(n-1)!又等于(n-1).(n-2)!,依此类推, 一直推到1!=1,。然后,再逆推回来即可求出结果。,7.6 函数的递归调用,第7章,【例7.7】用递归调用,编写求n!的程序。 分析: 函数fact( n)的函数体中出现fact(n-1),这正是函数的自身调用。主函数调用该函数计算4!。第一次调用时,形参n接收的值是4。进入函数体后,由于40,需要调用fact(n-1),即fact(3)。从而又开始了第二次调用该函数过程。依此类推,直到条件n=1成立,本次函数的自调过程结束,程序控制开始逐步返回。首先返回1!的结果为1,1乘n的当前值2,以其结果2返回到上次调用函数中。这样,以每次返回的值,乘以n的当前值的结果,作为本次调用的值返回到上次调用中。最后返回的是第一次调用fact(4)的值24,从而得到4!的计算结果。,7.6 函数的递归调用,第7章,程序代码: int fact( int n) /*递归函数*/ if(n main( ) /*主函数*/ int n, p; printf(“n=? ”); scanf(“%d”, /*打印返回的值*/ ,运行:n=? 4 显示:4!=24,7.7 指针与函数,第7章,7.7.2 数组作为函数参数,前面介绍了用变量做函数参数,此外,数组元素也可以做函数实参,其用法与变量做函数参数相同。指针变量作为函数参数传递的是变量的地址,而数组名作实参和形参,传递的是数组的首地址(属于指针传递)。 1数组元素作为函数实参 数组元素作为函数的实参,与变量作实参一样,是单向传递,即“数值传送”。只能将数组元素的值传递给被调函数的形参,不能带回变化的值。 2数组名作为函数参数 数组名表示数组的首地址,即数组名本身就是指针。因此,用数组名作为函数参数,是把数组的首地址作为实参传递给被调用函数形参,所以是指针传递参数。,7.7 指针与函数,第7章,7.7.3 返回指针的函数,一个函数可以返回一个int型、float型、char型的数据,也可以返回一个指针类型的数据(即地址)。 返回指针值的函数定义的一般形式为: 其中,函数名前面的“*”号表明这是一个指针型函数,即函数的返回值是一个指针。类型标识符表示了返回的指针值的数据类型。,类型标识符 * 函数名(形参列表) 函数体 ,7.7 指针与函数,第7章,7.7.4 函数的指针和指向函数的指针变量,1指向函数的指针变量的定义 一个函数在编译时,系统为函数代码分配一段连续的存储空间,这段存储空间的起始地址(又称入口地址)称为这个函数的指针。函数名就是该函数所占内存区的首地址。把函数的首 地址赋予一个指针变量,通过这个指针变量就可以引用该函数。 指向函数的指针变量定义形式为: 类型 (*指针变量名)(); 这里的“类型”是指针变量所指向的函数的类型,即函数返回值的类型。,7.7 指针与函数,第7章,7.7.4 函数的指针和指向函数的指针变量,2用函数指针变量调用函数 用函数指针变量调用函数时,只需将(*指针变量名)代替函数名,在后面的括号中根据需要写上实参。 使用函数指针变量还应注意以下两点: 对指向函数的指针变量,不存在p+、p-、p+i运算。 应注意区分函数指针变量和返回指针的函数,这两者在写法和意义上的区别。 3用指向函数的指针作函数参数 实现方法: 函数名作为实参,指向函数的指针变量作为形参,进行函数入口地址的传递。这样,通过函数地址的传递,在被调用函数中,调用实参传递过来的其他函数。,7.8 变量的作用域与存储类别,第7章,7.8.1 变量的作用域,所谓变量的作用域就是指变量能被有效引用的范围。从“变量的作用域”角度来分,C语言将变量分为局部变量和全局变量。 1局部变量 局部变量是在函数内部定义的变量,其作用域是从定义位置起,到函数结束。 说明: (1)主函数main中定义的变量,只在主函数中有效。 (2)不同函数中可以使用相同名字的变量,因为它们在内存中被分配不同的内存单元。 (3)形参也是局部变量,因为形参的作用域仅限于该函数内部。 (4)在一个函数内部,可以在复合语句中定义变量,这些变量只在本复合语句中有效。复合语句也称为“分程序”或“程序块”。,7.8 变量的作用域与存储类别,第7章,7.8.1 变量的作用域,2全局变量 在函数之外定义的变量称为全局变量。全局变量可以被本文件中其它函数使用。它的作用范围是,从定义变量的位置开始到源文件结束。 说明: (1)设置全局变量的优点是:增加了函数间数据联系的渠道。由于在同一文件中所有函数都能引用全局变量的值,这样,在一个函数中改变了全局变量的值,就能影响到其他函数,相当于各函数间有直接的传递通道。由于函数调用只能返回一个值,因此,有时可以通过全局变量得到多个返回值。 (2)全局变量在整个程序执行过程中都占用存储单元,使用全局变量过多,会降低程序的清晰性和通用性。 (3)在同一源文件中,外部变量与局部变量可以同名,因为它们的作用范围内不同,所以,相互没有影响。,7.8 变量的作用域与存储类别,第7章,7.8.2 变量的存储类别,在C语言中,每一个变量或函数都有两个属性:数据类型和存储类型。数据类型如int等,指的是数据的取值范围。存储类型指数据在内存的存储方法。存储方法分为两类:静态存储和动态存储。 1静态存储与动态存储 静态存储方式:程序运行期间,变量在静态存储区分配固定的存储空间。 动态存储方式:程序运行期间,变量在动态存储区根据需要动态的分配存储空间。 不同的存储方式决定了变量的生存期。从变量的作用范围,又可把变量分为四种:自动Auto、寄存器register、静态static、外部extern。下面分别介绍。,7.8 变量的作用域与存储类别,第7章,7.8.2 变量的存储类别,2Auto型变量 auto型变量是在函数内定义的变量,自动变量所在的函数或复合语句执行时,系统动态为相应的自动变量分配存储单元。函数的形参也属于auto型变量。当函数执行结束时,释放其空间。它的作用域局限于该函数。 3Register型变量 register变量又称寄存器变量。在程序运行中,若某个变量使用频繁,比如循环的次数为上万次,为提高运行速度,C语言允许将局部动态变量的值,放在CPU的寄存器中,直接参加运算,不再和内存打交道。这是因为寄存器的存取速度远高于内存。,7.8 变量的作用域与存储类别,第7章,7.8.2 变量的存储类别,4Extern型变量 extern型变量是在函数外定义的变量,缺省时系统默认为外部变量。 外部变量的定义位置是在所有函数体之外。当一个变量定义为“extern”型或默认存储类型说明时,一个文件的多个函数都可以使用该外部变量,其它文件也可以使用该变量。 5static静态变量 静态变量与auto、Register型变量不同,该变量在静态存储区存放,所分配的存储单元在程序运行中始终占用。静态变量分为内部静态变量和外部静态变量两种。,7.8 变量的作用域与存储类别,第7章,7.8.2 变量的存储类别,6存储类别小结 变量的存储方式分类如下:,7.9 内部函数和外部函数,第7章,7.9.1 内部函数,如果一个函数只能被本文件中其它函数所调用,则称为内部函数。内部函数称为静态函数。使用内部函数,可以使函数只局限于所在文件。,7.9 内部函数和外部函数,第7章,7.9.2 外部函数,在函数定义时,如果在类型的前面加上关键字extern,则表示此函数是外部函数,可供其他文件调用。如果在定义函数时省略extern,则隐含为外部函数。本书前面所用的函数都作为外部函数。 通常,当函数调用语句与被调函数不在同一文件时,应当在调用语句所在函数说明部分用extern说明所调用的函数是外部函数。,7.10 程序举例,第7章,排序算法有多种,比较经典的有冒泡法和选择法,冒泡法在第六章中已经进行了详细的分析,下面我们用选择法来进行编程。 【例7.20】用选择法对10个学生的成绩由小到大排序,并计算平均成绩。排序过程及求平均值均由函数来实现。 分析: 所谓选择法就是先找最小值,其排序操作过程是:先将10个数中的第1个数a0与后面的9个数比较,若大于后面的数则进行对换,第一轮结束,a0中是最小值;再将a1与它后面的8个数进行比较,直到a1是剩余9个数中的最小值;.。每比较一轮,找出未经排序的数中最小的一个。共应比较9轮。,7.10 程序举例,第7章,下面以七个数为例来说明选择排序的步骤: A0 a1 a2
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 体育概论试题及答案
- 平安优才计划面试题及答案
- 巡检电工面试题及答案
- 许昌陶瓷职业学院《中国音乐史与欣赏(一)》2023-2024学年第二学期期末试卷
- 山西药科职业学院《山水画空间生成原理》2023-2024学年第二学期期末试卷
- 重庆交通职业学院《生化微生物基础》2023-2024学年第二学期期末试卷
- 商丘学院《中学教师美学素养III(绘画)》2023-2024学年第二学期期末试卷
- 2023浙江省足部按摩师大赛理论复习题复习试题及答案
- 国庆节主题班会861
- 苏教版五年级上册数学第三单元小数的意义和读写 课件
- 贵州省贵阳市普通中学2021-2022学年八年级下学期期末监测考试物理试题
- 2023年杭州市滨江区数学六下期末质量跟踪监视试题含解析
- 特种设备日管控、周排查、月调度模板
- 普通外科学科建设课件
- 《爱的教育》课外阅读指导课正式版
- 图解C编程知到章节答案智慧树2023年宁波大学
- 2020年现行房屋建筑工程常用材料进场取样复试检验项目规范
- 分保、等保、关保、密评之间联系与区别
- PFMEA模板完整版文档
- 湿润烧伤膏外治WagnerⅠ~Ⅱ级糖尿病足正邪分争期溃疡的疗效观察
- 沪科版八、九年级物理实验目录分类及仪器
评论
0/150
提交评论