




免费预览已结束,剩余60页可下载查看
下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第5章函数 计算机学院C课组 2 函数 clrscr 功能 是清屏 将插入点置于0行0列 clrscr 3 第5章函数 模块化程序设计是面向过程程序设计的很重要的方法 C语言中的函数体现了这种思想 本章主要介绍 1 函数的定义2 模块化程序设计的实现方法3 函数的定义及函数的调用方式4 内部函数和外部函数的定义和调用方法等 4 5 1C函数与C程序结构 模块化程序特点 模块化程序具备逻辑清晰 层次分明的特点结构 具体应用 在C源程序中 用户可将算法分解成一个个相对独立的函数模块 称为用户函数 然后 通过函数调用来使用这些函数 5 模块化程序设计 C语言的函数作为一个模块一般应依据下面两个原则 1 界面清晰 函数的处理子任务明确 函数之间数据传递越少越好 2 大小适中 若函数太大 处理任务复杂 导致结构复杂 程序可读性较差 反之 若函数太小 则程序调用关系复杂 这样会降低程序的效率 6 模块化软件结构的示意图 一个C语言程序由主函数和若干个 0个用户函数 组成 C语言中的函数没有隶属关系 即所有的函数都是独立定义的 不能嵌套定义 7 函数是通过调用来执行的 允许函数间互相调用 也允许直接或间接的递归调用其自身 例5 1 用户定义一个无参函数用来输出信息 voidprintstar printf n main函数可以调用任何一个函数 而其他函数不能调用main函数 例如 main printstar 8 9 调用另一个函数的函数称为主调函数 被调用的函数称为被调函数 函数的四种形式 a 从使用的角度来分为用户函数和系统函数b 从形式上分成有参函数和无参函数c 从作用的范围分为外部函数和内部函数d 从返回值的角度分成有返回值函数和无返回值函数 voidprintstar 无参 无返回值 floatarea floata floatb 有参 有返回值 printf n 系统函数 有参 有返回值 getchar 系统函数 无参 有返回值 10 5 2函数的定义及构成 函数要先定义后使用 函数定义的一般格式为 存储类型 数据类型 函数名 形式参数表 说明部分语句部分 通常把函数名和形参的说明部分称为 函数头 用花括号括起来的部分称为 函数体 11 函数具有以下特征 1 存储类型定义函数时 存储类型 可以是extern或static两种关键字说明 2 数据类型定义函数时 数据类型 是用来说明该函数返回值的类型 可以是整型 字符型 实型 指针型和其它构造类型 如果省略 则系统默认为int型 3 函数名函数名是一个标识符 它的命名规则同变量相同 4 形式参数表形式参数 简称形参 的说明形式如下 数据类型形式参数1 数据类型形式参数2 12 5 函数体由 括起来的部分称为函数体 由说明部分和语句部分组成 6 函数的返回值返回值可以是常数 变量或表达式 也可以是指针 但不能是数组名或函数名 return表达式 return 表达式 例如 returns 13 关于return语句说明如下 如果不需要从被调函数带回返回值可以不要return语句 一种情况是将函数类型定义为void型 也叫空类型 例如 voidprintstar 2 还可以用不带表达式的return作为函数的逻辑结尾 这时 return的作用是将控制权交给调用函数 而不是返回一个值 也可以不用return return 14 return语句是函数的逻辑结尾 不一定是函数的最后一条语句 一个函数中允许出现多个return语句 但每次只能有一个return语句被执行 if x 0 return 1 elseif x 0 return0 elsereturn1 1x0 Y 15 5 3函数的调用5 3 1函数的调用 函数调用格式 函数名 实参表 函数的调用过程是 1 如果是有参函数 为形式参数分配存储单元 将实参的值计算出后依次赋予对应的形参 称为值传递 传值 在C语言中这种数据传递是单向的 2 执行函数体 为其中的变量分配存储单元并执行函数体中的可执行语句 当执行到 返回语句 时 计算返回值返回主调函数继续运行程序 如果是无返回值函数 则省略此操作 系统将释放本函数体中定义的变量 静态型变量不释放 同时收回分配给形参的存储单元 如果是 无参函数 则无需进行参数传递 16 例5 3 调用函数实现求长方形的面积 includefloatarea floata floatb 定义函数area 形参为a b floats s a b returns 变量s带回函数值 返回主调函数 voidmain floatlength width s scanf f f 17 intsum intx inty intz intm m x y z returnm includemain inti j k s printf inputthreeintegers scanf d d d 例5 4 编写程序 计算3个不为0的整数之和 18 例如 求两个数中的最大数 includemax floatx floaty floatz z x y x y returnz main floata b intc scanf f f 19 函数调用时要注意以下问题 1 如果实参表中包含多个实参 则各实参用逗号隔开 实参与形参的个数应相等 且类型应一致 2 函数的调用也可以出现在表达式中 这时要求函数带回一个确定的值以参加表达式的运算 s 5 sum i j k 3 对实参表求值的顺序TurboC是按从右到左的顺序求值 20 例5 5 写出程序运行结果 includeintf inta intb if a b return1 elseif a b return0 elsereturn 1 main inti 2 p p f i i 传递的都是3 printf d p 21 4 函数定义的类型就是返回值的类型 函数调用时 如果return中的表达式类型与函数类型不一致 则编译系统自动将表达式的类型转换成函数的类型后返回 intmax floatx floaty floatz z x y x y returnz 返回整型值 输入 3 5 4 8 22 4 调用函数与被调用函数的相对位置关系一个程序文件中可能包含若干个函数 函数在其中所处的位置代表函数定义的顺序 同时也决定了它的作用域 若 调用点位于被调用函数后则不需说明 而调用点位于被调用函数前 则必须进行函数声明后才能调用 声明时要说明被调用函数的返回值的类型 函数名 函数的形式参数表 其中形参都要在形参表中一一列举 函数声明的格式为 类型名被调用函数的函数名 23 例5 6 观察下面程序中声明函数与调用点的位置 include includelongfac intx 声明函数fac 形参为int类型 此时函数作用域开始voidmain intn printf inputaninteger scanf d longfac intx inti longy 1 for i 1 i x i y y i returny 24 若被调用函数的函数值是整型或字符型 则均可省略上述函数声明 例如 求两个数中的最大数在函数的外部已做了函数声明 则在各个主调函数中不必对所调用的函数再作声明 例如 floatf1 float float charf2 char intf3 float main floatf1 floata floatb charf2 charc intf3 floatd 在main中不用对函数f1 f2 f3进行声明 25 5 函数的调用可以是嵌套的 即在调用一个函数的过程中可以再调用另一个函数 C语言不允许嵌套定义 但可以嵌套调用 在主函数中调用其他函数 include 调用系统函数voidprintstar void 用户函数 函数头 cout endl voidprint message void 用户函数 函数头 cout WelcometoC endl printstar 调用用户函数 intmain void printstar 调用用户函数print message 调用用户函数return0 26 例5 7 通过函数嵌套调用输出信息 includevoidstar 函数声明voidmessage 函数声明voidmain voidstar 调用用户函数starmessage 调用用户函数message voidstar 用户函数 函数头 printf n voidmessage 用户函数 函数头 printf WelcometoC n star 在函数执行数过程中调用star函数 27 5 3 2C 中函数形参默认值 C 中函数在定义时可以预先定义一个默认的形参值 在函数调用时 如果给出实参 则用实参初始化形参 如果没有给出实参 就用预先给定的默认值 例5 8 带默认形参值的函数的声明与定义 intadd inta 5 intb 9 形参a与b的默认值分别为5和9 returna b 两数相加 voidmain add 15 20 用实参初始化形参 实现15 20add 15 形参a用15 b用默认值9 返回值为24add a b都用默认值 返回值为14 28 5 4C 中的函数重载 重载就是在程序中相同的函数名对应不同的函数实现 函数重载允许程序内出现多个名称相同的函数 这些函数可以完成不同的功能 并且带有不同的类型 不同的形参个数及不同的返回值 使用函数重载 就可以把功能相似的函数名命名为一个相同的标识符 使程序结构简单 易懂 29 例5 9 求3个数当中最大数 共考虑3种数据类型 分别是整型 双精度型和长整型 includeusingnamespacestd intmax inta intb intc 函数声明doublemax doublea doubleb doublec 函数声明longmax longa longb longc 函数声明intmain inti1 i2 i3 i cin i1 i2 i3 输入3个整数i max i1 i2 i3 求3个整数中的最大者cout i max i endl doubled1 d2 d3 d 30 cin d1 d2 d3 输入3个双精度数d max d1 d2 d3 求3个双精度数中的最大者cout g1 g2 g3 输入3个长整数g max g1 g2 g3 求3个长整数中的最大者cout g max g endl return0 31 intmax inta intb intc 定义求3个整数中的最大者的函数 if b a a b if c a a c returna doublemax doublea doubleb doublec 定义求3个双精度数中的最大者的函数 if b a a b if c a a c returna longmax longa longb longc 定义求3个长整数中的最大者的函数 if b a a b if c a a c returna 32 5 5函数间的数据传递 函数间的数据传递是指主调函数向被调函数传送数据及被调函数向主调函数返回数据 函数间的数据传递可以通过参数 实参 返回值 全局变量来实现 参数传递数据的方式主要有两种 值传递和地址传递传值传递的是具体数据 传址是传递的变量 数组元素 或数组的地址 实质上两种方式均为值传递 为数值与地址值 地址值 33 5 5 1值传递方式 值传递方式所传递的是参数值 调用函数时 将实参的值计算出来传递给对应的形参 实参对形参的值传递只是单向传递 不能由形参传结实参 这是由于在内存中实参和形参使用的是不同的存储单元 因此 在执行一个被调函数时 形参的值如果发生变化 并不会改变主调函数的实参值 34 例5 10 考察下面的程序 能否通过函数调用实现求变量的相反数 includemain intx voidopposition int scanf d 35 例5 11 设一维数组存放了10个学生的成绩 求不及格的人数intflag floatscore if score 60 return1 elsereturn0 main floatscore 10 inti num 0 printf input10scores n for i 0 i 10 i scanf f 36 5 5 2地址传递方式 地址传递方式不是传递数据本身 而是数据的内存单元的地址传递给形参 简称传址 实参和形参共同占用相同的存储单元 因此在函数中改变了形参存储单元的值 将会使实参随之变化 可见 在形参和实参为地址传送方式时 被调用程序中对形参的操作实际上就是对实参的操作 间接的实现了数据的双向传递 37 例5 12 数组a中存放了一个学生5门课程的成绩 求平均成绩 floataverage floatarray 5 inti floatav sum 0 for i 0 i 5 i sum sum array i av sum 5 returnav main floatscore 5 av inti printf input5scores n for i 0 i 5 i scanf f input5scores 8472908765 averagescoreis79 60 38 说明 用数组名也可用数组元素地址作函数参数要求 在主调函数和被调函数分别定义数组且数组的类型应该一致执行机制 C编译系统只将实参数组的首地址传给形参数组关于形参数组 可以指定大小 floataverage floatarray 5 可以不指定大小 另设一个参数传递实参数组的大小 但在定义数组时在数组名空的方括号不可少 这时形参数组可以随实参数组而动态变化 例如 39 被调函数中形参数组没有定义大小 由n来接收长度值 floataverage floatarray intn inti floatav sum 0 for i 0 i n i sum sum array i av sum n returnav main floatscore1 5 84 72 90 87 65 floatscore2 10 72 68 93 55 89 75 62 88 95 70 printf averagescore1is 5 2f n average score1 5 printf averagescore2is 5 2f n average score2 10 例5 17 5 18 40 5 5 3返回值方式 在调用函数后直接返回一个数据到主调函数中 注意下列几点 1 定义函数时 在函数头应给出 数据类型 指出该函数返回值的数据类型 2 定义函数时 函数体中应有 return 表达式 3 传递的数据可以是整型 实型 字符型及结构型等 但不能传整个数组 4 只能传递1个数据 而且只能是从被调函数将数据传给主调函数 5 当被调用函数的数据类型与函数中return后面表达式的类型不一致时 表达式的值将被自动转换成函数的类型后传递给调用函数 41 例5 14 调用函数 求两整数之差 includeintsub intx floaty voidmain inta n floatb scanf d f intsub intx floaty floatz z x y returnz 9087 3 运行结果为n 2 42 5 5 4全局变量传递方式 在程序执行的全程有效的变量称为全局变量 又称外部变量 作用域 是从定义处开始到整个程序结束 同时 还可以被任何一个函数使用内存的使用 在整个程序的运行中一直占用着存储单元 作用 可以利用全局变量在函数间传递数据 使得通过函数调用得到多个返回值 43 includeints1 s2 s3 intvs inta intb intc intv v a b c s1 a b s2 b c s3 a c returnv main intv l w h printf inputlength widthandheight n scanf d d d 例5 15 输入长方体的长宽高l w h 求体积及三个面x y x z y z的面积 44 例5 16 外部变量与内部变量同名inta 3 b 5 max inta intb intc c a b a b returnc main inta 8 printf d max a b 形参a b的作用范围 局部变量a的作用范围 全局变量a b的作用范围 45 说明 好处 设全局变量的作用是增加了函数间数据联系的渠道 缺点 1 利用全局变量实现函数间的数据传递 削弱了函数的内聚性 从而降低了程序的可靠性和通用性 2 全局变量在程序的全部过程中都占用存储单元 46 例5 17 静态局部变量的使用 includef voidmain f f f f staticinta 1 变量a是静态局部变量 在此函数中有效autointb 0 变b是动态变量 在此函数中有效a a 1 b b 1 printf a d b d n a b 47 5 5 5C 中访问全局变量 例5 18 作用域操作符的使用 doubleA 全局变量Avoidmain intA 局部变量AA 5 为局部变量A赋值 A 2 5 为全局变量A赋值cout A end1 输出局部变量的值5cout A end1 输出局部变量的值2 5 48 5 6递归调用与递归函数 C语言允许函数进行递归调用 即在调用一个函数的过程中 又出现直接或间接地调用该函数本身 前者称为直接递归 后者称为间接递归 递归调用的函数称为递归函数 由于递归非常符合人们的思维习惯 而且许多数学函数 算法或数据结构都是递归定义的 因此递归调用颇具实用价值 49 递归函数的特点递归函数常用于解决那些需要分多次求解 并且每次求解过程基本类似的问题 递归函数内部对自身的每一次调用都会导致一个与原问题相似而范围要小的新问题 构造递归函数的关键在于寻找递归算法和终结条件 终结条件是为了终结函数的递归调用而设置的一个标记 注意 递归调用不应也不能无限制的执行下去 所以必须设置一个条件来检验是否需要停止递归函数的调用 终止条件的设置可以通过分析问题的最后一步求解而得到 50 递归函数的设计 递归问题的一般描述 用递归函数求n 递归结束的条件 f k 常量递归计算公式 f n 含有f n 1 的表达式函数递归的一般结构 数据类型f n if n k return 常量 elsereturn f n 1 的表达式 51 例5 19 用递归函数求n 分析 首先将求n 的函数拿来用1 如果求n 可以通过求 n 1 完成 而求 n 1 必须要求出 n 2 以次类推 直到最后求出1 这就是递归调用公式 2 那么当n为1时可得出结果就是1 1就是结束条件 有这种规律的计算问题就可以设计递归函数调结构程序 52 includefloatfac intn floatf if n 1 f fac n 1 n elseif n 0 n 1 f 1 elsef 1 returnf voidmain intn floaty printf Inputaintegernumber scanf d 53 例5 20 用递归函数求fibonacci数列的某一项的值 includeintfib inti if i 1 54 习题五 5 传值 main inta is not 10 scanf d includeintrunnian intb intc if b 100 0 55 5 7内部函数和外部函数 语言程序中函数分为两类 即内部函数和外部函数 它们以是否可以允许其它程序文件调用来区分的 允许其它程序文件调用的函数称为外部函数 不允许其它程序文件调用的函数称为内部函数 56 5 6 1内部函数 一个源文件中定义的函数只能被本文件中的函数调用 而不能被其它文件中的函数调用 这种函数称为内部函数 静态函数 使用关键字static定义内部函数 其格式为 static数据类型函数名 形参表 例如 staticintf inta intb 内部函数的作用域 内部函数的调用范围只局限于本文件 57 5 6 2外部函数 外部函数是指允许其他文件调用的函数 使用关键字extern定义外部函数 其格式为 extern数据类型函数名 形参表 例如 externintf inta intb 系统默认 如在函数定义中没有说明extern或static则默认为外部函数 在一个源文件的函数中调用其它源文件中定义的外部函数时 应用extern说明被调函数为外部函数 58 5 7函数应用程序举例 例5 21 编写一个函数 求一个整数的所有正因子 includevoidgene intn intd for d 1 d n d if n d 0 printf d n d main intn printf Inputintegern scanf d 59 例5 22 编写一个函数 求一个字符串中英文单词的个数 单词之间用空格符 换行符 跳格符隔开 main charstring 81 printf Inputastring n gets string printf Thereare dwordsinthestring n wordnum string includeintwordnum charstr inti num 1 charch for i 0 ch str i 0 i num returnnum 60 例5 23 编写一个函数 用选择法将一维数组排序 数组长度为10 元素由小到大排序 算法分析 每比较一轮 找出一个未经排序数中的最小值 因此共须9轮排序 下面以5个数为例说明选择法排序的步骤 a 0 a 1 a 2 a 3
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年邵东辅警考试题库及答案
- 中国广电山南市2025秋招写作案例分析万能模板直接套用
- 中国移动河源市2025秋招笔试模拟题及答案
- 泰安市中石化2025秋招笔试模拟题含答案市场营销与国际贸易岗
- 运城市中石化2025秋招笔试模拟题含答案炼油工艺技术岗
- 朝阳市中储粮2025秋招笔试性格测评题专练及答案
- 国家能源内江市2025秋招笔试言语理解与表达题专练及答案
- 昌吉回族自治州中石油2025秋招笔试模拟题含答案市场营销与国际贸易岗
- 中国移动池州市2025秋招供应链采购类专业追问清单及参考回答
- 2025年钣喷质检员考试题及答案
- 2025年镇江市中考英语试题卷(含答案)
- 航海船舶因应气象预报方案
- 铝合金介绍教学课件
- 电气班组安全教育培训课件
- 《2025同上一堂思政课》观后感10篇
- SY4201.2-2019石油天然气建设工程施工质量验收规范设备安装塔类检验批表格
- 电机的工作原理课件
- 设计质量意识培训课件
- 2025年四川省高考化学试卷真题(含答案解析)
- 2025年新玩家股东招募协议书
- 食品安全知识培训会议记录范文
评论
0/150
提交评论