程序设计基础 ——C语言第6章 函数_第1页
程序设计基础 ——C语言第6章 函数_第2页
程序设计基础 ——C语言第6章 函数_第3页
程序设计基础 ——C语言第6章 函数_第4页
程序设计基础 ——C语言第6章 函数_第5页
已阅读5页,还剩89页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

程序设计基础 第 6章 函数 1 函数 的调用、参数和返回值 函数的定义 第 6章 函数 函数的 嵌套调用 函数的声明 数组作为 函数 参数 函数的递归调用 内部函数和外部 函数 变量的作用域与生存期 综合应用举例 预处理命令 2 第 6章 函数 一 个庞大的 函数 会带来如下问题: 不可能稳定可靠 。 不可能精炼高效 。 不可能与时俱进 。 不可能控制精度 。 器 函数 3 【程序 6输入两个圆的半径,求圆环面积。 【 算法分析 】 输入第一个圆的半径,并计算第一个圆的面积。 输入第二个圆的半径,并计算第二个圆的面积。 计算圆环的面积,并输出。 第 6章 函数 4 第 6章 函数 【 程序 6法 1】 #I r1,r2,s1,s2, ); %f,& /*输入第一个圆半径 */ I*r1* /*求第一个圆的面积 */ ); %f,& /*输入第二个圆半径 */ I*r2* /*求第二个圆的面积 */ /*求圆环的面积 */ ss= if(I *定义 函数,函数的功能是:输入圆的半径并求圆的面积 */ r; ); %f,&r); /*输入圆的半径 */ I*r*r; /*返回圆的面积 */ s1,s2,s1=; /*调用 函数输入第一个圆的半径并求圆的面积 */ s2=; /*调用 函数输入第二个圆的半径并求圆的面积 */ /*求圆环的面积 */ ss=if(I *定义 函数,函数的功能是:输入圆的半径并求圆的面积 */ r; ); %f,&r); I*r*r; /*定义 函数,函数功能:计算圆环面积,并输出 */ s1, ss=if(( 2)自定义函数 你可以按照自己的意愿编写自己的函数,完成特定的功能 。 本章 重点介绍自定义函数。 10 函数 的定义 返回 值类型 函数名 (参数类型 1 形参 1, 参数类型 2 形参 2,) 函数体 【说明】 “ 函数名 ” 是函数的唯一标识,它的命名规则与变量一样 。 习惯 上的命名风格有两种 : 在 习惯 用 在 惯用 1 【程序 6-2(a)】 求两个数的最大值的函数 。 /*函数功能: 求 两个数的最大值 函数 参数: 整型 x,整型 y 函数 返回值:两个数的最大值 */ ax(x,y) xy?x:y; 函数 的定义 12 函数的调用、参数和返回值 变量 必须先定义,后 使用。 函数 也必须 先定义,后调用。 函数调用的一般 形式: 函数名 (实参 1,实参 2,); 【说明】 函数 定义 时,圆括号内的参数称为 形参 。 函数 调用 时,圆括号内的参数称为 实参 。 实参 与 形参 的 个数 应相等, 类型 应 一致 , 顺序 应 对应。 13 【程序 6-2(b)】 调用 函数的 函数。 # a=3,b=8; ax(a,b); /*调用 函数 */ %dn,a,b, ; 函数的调用、参数和返回值 14 函数的调用、参数和返回值 / * 程 序 6 - 2 ( b ) * /# i n c l u d e i n t m a i n ( )i n t a = 3 , b = 8 ;i n t n R e s ;n R e s = M a x ( a , b ) ; / * 调 用 M a x ( ) 函 数 * /p r i n t f ( % d 和 % d 的 最 大 值 是 : % d n , a , b , n R e s ) ;r e t u r n 0 ;/ * 程 序 6 - 2 ( a ) * /i n t M a x ( i n t x , i n t y )i n t r e s u l t ;r e s u l t = x y ? x : y ;r e t u r n r e s u l t ;实 参 a 和 x 和 -2(a)和 程序 6-2(b)合并在一起构成一个完整的 程序 。 3和 8的最大值是: 8 15 函数的调用、参数和返回值 【 说明 】 ( 1)函数 的返回值只能有一个。 ( 2) ( 3) 函数的 返回值 类型可以是除数组以外的任意类型,也可以是示没有返回值 。 ( 4) 如果函数的返回值类型和 以函数的返回值类型为准 。 等价于 16 #*函数功能: 求 两个数的最大值 函数 参数: 整型 x,整型 y 函数 返回值:两个数的最大值 */ ax(x,y) xy?x:y; a=3,b=8; ax(a,b); /*调用 函数 */ %dn,a,b, ; 函数定义在函数调用之前 函数的定义 函数的调用 【程序 6程序 6-2(a)和程序 6-2(b)合并,求两个数的最大值 。 17 函数的 声明 函数定义 都要写在 函数调用 前面 吗 不是 函数定义 写 在 函数 调用 的后面 ,就 需要在 函数 调用 之前 进行 函数声明 。 函数声明 的 格式: 函数定义的首部(函数定义去除函数体部分),再加一个分号 。 ax(x,y); ax( 函数声明 有两种形式: ( 1) 返回值类型 函数名 (参数类型 1 参数名 1,参数类型 2 参数名 2,); ( 2) 返回值类型 函数名 (参数类型 1, 参数类型 2,); 等价于 18 #ax(x,y); /*函数的声明 */ a=3,b=8; ax(a,b); /*调用 函数 */ %dn,a,b, ; /*函数功能: 求 两个数的最大值 函数 参数: 整型 x,整型 y 函数 返回值:两个数的最大值 */ ax(x,y) xy?x:y; 【程序 6程序 6函数的声明)。 函数定义在函数调用之后 函数的定义 函数的调用 函数的声明 19 # a=3,b=8; ax(x,y); /*函数的声明 */ ax(a,b); /*调用 函数 */ %dn,a,b, ; /*函数功能: 求 两个数的最大值 函数 参数: 整型 x,整型 y 函数 返回值:两个数的最大值 */ ax(x,y) xy?x:y; 【程序 6程序 6数的声明在函数内部 ) 。 函数声明在函数内 部 函数的定义 函数的声明 函数的调用 20 函数的 声明 【 程序 6调用自定义函数求奇数数列和: 1+3+5+7+9+(2n0)。 【 算法分析 】 编写主函数。 主 函数将完成 3个操作 : 输入 求和元素的个数 n 调用 函数求数列 和 输出结果 21 n=0; ; 请输入 n:); %d,&n); n); 奇数和为 %ldn, ; 函数的 声明 调用函数 输入 输出 22 函数的 声明 测试主函数。 可 在 函数 之前加上 自定义的 空函数 : n) 这个函数的函数体是空的,称为 空函数 。 加入 了空函数之后程序可以运行,但不能得到希望的结果。使用空函数只是为了 测试主函数 。 23 函数的 声明 编写 确定函数的定义 形式 。 函数 的首部为 : n) 编写函数 体 。 注意: 函数体内定义的各个变量名不能与函数的参数同名 ,函数 的返回值通过 24 【 程序 6 #*函数功能: 求 奇数数列 1+3+5+7+.+(2和 函数 参数: 求和 元素的个数 n,整型 函数 返回值:奇数数列和 */ n) i=0; ; i=1;ii n t m a i n ( ). . .r e s u l t = f u n 1 ( . . . ) ;. . .r e t u r n 0 ;i n t f u n 1 ( . . . ). . .f u n 2 ( . . . ) ;. . .i n t f u n 2 ( . . . ). . . m a i n ( ) f u n 1 ( ) f u n 2 ( )26 函数的 嵌套调用 【 程序 6计算 1!+2!+3!+n!的值,要求用 函数的嵌套调用 方式实现。 【 算法分析 】 该 问题可分解为以下两个子问题: 依次计算自然数 1 求这些阶乘值得累加和。 第一 个函数 参 n,识别 要计算的是哪个自然数的阶乘 。 第二 个函数 个形参 n , 明确 对多少个数 求和。 27 【 程序 6 #*函数功能: 求 n!的函数 函数 参数: 整型 n 函数 返回值: n!的值 */ n) i; ; i=1;i /*函数功能: 求 n!的函数(用递归函数实现) 函数 参数: 整型 n 函数 返回值: n!的值 */ n) ; if(n=0) /*递归出口 */ ; /*递归调用 */ n; n; 请输入 ); %d,&n); n); %d!=%ldn,n, ; 请 输入 3 6!=120 33 递归函数 以 计算 3!为例,具体描述递归程序的执行 过程 。 F a c t o r i a l ( 3 ) 3 ! = 2 ! 3F a c t o r i a l ( 2 ) 2 ! = 1 ! 2F a c t o r i a l ( 1 ) 1 ! = 0 ! 1F a c t o r i a l ( 0 ) 0 ! = 11 ! = 1 1 = 12 ! = 1 2 = 23 ! = 2 3 = 6递 推 递 推 递 推 回 归 回 归 回 归 34 实现 递归 分为以下两个阶段: ( 1) 递推阶段 。将原问题不断分解为新的子问题,不断推进直到已知条件,即递归结束条件。 ( 2) 回归阶段 。从已知条件除法,按递推的逆过程逐一求值回归,直到递推的 开始 处 结束 回归阶段。 通用 的 递归函数体 的形式表示如下: 归终止条件成立 ) 归公式的初值 ; 归函数调用返回的结果值 ; 递归函数 35 递归函数 【注意】 所有 能用 递归 方法解决的问题都可以用 非递归 方法来实现 。 采用 递归 方式 的 优点 : 算法 简单 、 容易实现 , 代码 简洁 。 采用递归方式的 缺点 : 程序 的 运行效率 低 。 36 【 程序 6编程求解汉诺塔问题。 【 算法分析 】 1、 如何 表示将第 木桩移动到 整型变量 符型变量 符型变量 2、 如何 实现递归函数?假设 ,借助于木桩 。 a,b,c); 3、 第 ,借助于木桩 可以用如下三步实现。 a,c,b); n,a,b); c,b,a); 37 数组作为函数参数 一维数组作为函数参数 二维数组作为函数参数 38 一维数组作为函数参数 39 【程序 6一维数组 放 5个学生成绩,用一个函数求学生的平均成绩。 【 算法分析 】 在 函数中定义一个 入 5个学生的成绩存放到 设计 一个函数 来求学生的平均成绩 。 把 40 【 程序 6 #*函数功能: 求 5个学生成绩的平均值 函数 参数: 数 返回值: 5个学生成绩的平均值 */ ) i; ,i=0;i /*函数功能: 求 34矩阵的最大值 函数 参数: 整型 二维数组 数 返回值:矩阵的最大值 */ 4) i,j,0; i=0;ij; 4=1,3,5,7,2,4,6,8,15,17,34,12; 最大值是: %dn,; ; 实参 形参 间 。 44 二维数 组作为函数参数 【 说明 】 4,n); 最大值是: %dn,); 完整程序参见 【 程序 6。 变量的作用域与生存期 局部变量 全局变量 变量的存储类别 小结 45 46 局部变量 局部变量 : 定义 在函数内部的变量。 ( 1)如果变量定义在 函数体 内 ,那么该变量的作用域 是从 变量定义处到 本函数结束 处。 ( 2)如果变量定义在函数内部的某个 复合语句 中,那么该 变量的 作用域是从 变量定义 处到该 复合语句结束 处 。 系统在局部变量进入作用域时为其分配内存空间,并在离开作用域时自动释放这些内存 空间 。 47 i n t f ( i n t a )i n t b ;i f ( a 0 )i n t c = 0 ;. . .i n t m a i n ( )i n t a , b ;. . .a 、 b 的 作 用 域c 的 作 用 域a 、 b 的 作 用 域48 全局变量 全局变量 : 定义 在 函数外部 的变量 ,作用域 是从 变量定义 处开始到程序结束 处。 全局变量从程序运行起即占据内存空间,在程序整个运行过程中可随时访问,程序退出时释放内存。 49 i n t p = 1 , q = 5 ; / * 全 局 变 量 * /f l o a t f 1 ( i n t a ) / * 定 义 函 数 f 1 * /i n t b , c ;c h a r c 1 , c 2 ; / * 全 局 变 量 * /c h a r f 2 ( i n t x , i n t y ) / * 定 义 函 数 f 2 * /i n t i , j ; i n t m a i n ( ) / * 主 函 数 * /i n t m , n ;c 1 、 c 2 的 作 用 域p 、 q 的 作 用 域50 全局变量 和某个函数的 局部变量 同名 时, 局部变量 将 屏蔽 同名的 全局变量 。 【 程序 6 #a=3,b=5; /*a、 (a,b) /*a、 ab?a:b; ) a=8; /*(%dn,a,b); ; 8 8 5 8 5 8 51 变量的存储类别 程序运行 时的 存储空间 被分为 代码区 和 数据 区 ( 静态 存储区 和 动态存储 区 )。 局部变量 采用 动态存储方式 ,在函数调用开始时分配动态存储空间,函数结束时释放这些空间 。 全局变量 采用 静态存储方式 ,在程序开始执行时给全局变量分配存储区,程序执行完毕释放 。 代码区静态存储区动态存储区52 定义变量 : 存储类别 类型 变量名; 存储类别: 声明自动变量 声明寄存器变量 声明静态变量 声明外部变量的作用范围 变量的存储类别 53 1. 所有局部变量 都是 , 等价于 ,2. 在 做 寄存器 。 把 频繁访问的数据存放在寄存器里 ,可以提高 程序 的 性能。 现在计算机的 编译系统 能够识别 使用频繁的变量,从而自动将这些变量放在寄存器 中。 54 静态 变量 有两种: 静态局部变量 和 静态全局变量 。 例如: b) a=2; /*静态局部变量 a*/ 静态 局部变量 的初值只在编译期赋值一次 ,如果 变量定义时没有进行初始化,则系统自动存储 0值或 空字符 。 静态 局部变量 具有“记忆性”,它能默认记住上一次操作后的结果。 55 【程序 6分析以下程序的结果,注意静态局部变量的使用 。 #b) a=2; /*静态局部变量 a*/ a=a+b; %dn,a); i; i=1;i ax(x,y) /*定义 z; z=xy?x:y; z); ,B; /*外部变量声明 */ %dn,B); ; =13,B= /*定义外部变量 */ 定义在后 调用在前 要加声明 59 【程序 6多文件中 /*源文件 #; /*在源文件 */ n) A=A*n; /*在源文件 */ /*源文件 #; /*在源文件 进行外部变量的声明 */ A=8; /*在源文件 */ ); %dn,A); ; 源文件 1中定义 源文件 2中声明 源文件 2中使用 60 /* ; /*静态全局变量 */ ) /* ; /*(n) A=A*n; 【 例 】 静态全局变量和 仅限 在多人合作的程序设计过程中,为每个文件的全局变量 前加上 人 可以独立地在其设计的文件中使用相同 的全局变量 名而 互不干扰。 61 小结 变量作用域 变量存储类别 特 征 局部变量 自动变量 作用域在函数内部 , 存于动态存储区 ,函数执行结束 , 变量值消失 静态变量 作用域在函数内部 , 存于静态存储区 ,函数执行结束 , 变量值保留 寄存器变量 作用域在函数内部 , 存于寄存器存储区 ,函数执行结束 , 变量值消失 全局变量 静态外部变量 作用域从定义开始到程序结束 , 存于全局存储区 , 程序执行结束 , 变量值消失 外部变量 允许在整个程序中使用 , 存于全局存储区 , 程序执行结束 , 变量值消失 62 小结 动态存储变量 自动变量 , 仅作用于本函数 , 函数调用时临时分配存储单元 , 函数结束时 , 其值消失 寄存器变量 , 仅作用于本函数 , 函数调用时临时分配存储单元 , 函数结束时 , 其值消失 函数中的形式参数 , 仅作用于本函数 , 函数调用时临时分配存储单元 , 函数结束时 , 其值消失 静态存储变量 静态局部变量 , 仅作用于本函数内 , 在程序编译时赋初值 , 其值保留到程序结束时消失 静态外部变量 , 作用于从定义开始到程序结束 , 在程序编译时赋初值 , 其值保留到程序结束时消失 外部变量 , 本文件中的任何函数或其它文件可引用 ,其值保留到程序结束时消失 内部函数和外部函数 内部函数 63 外部函数 64 内部函数 内部 函数 : 只能 被其所在文件内的函数调用 , 而不能被其他文件内的函数 调用 。 内部 函数 的函数首部为: 回值类型 函数名 (参数类型 1 形参 1,参数类型 2 形参 2,) 例如: a,b) 内部 函数 也称为 静态函数 。 同一项目中 , 不同 的人可以分别编写不同的函数 , 而不用担心所用函数是否会与其他文件中函数 同名 。 65 外部函数 外部 函数 : 可 供其他文件调用 。 外部函数 的函数首部可以 写为: a,b) 定义 函数时 , 省略 隐含为 外部函数 。 本 书前面所用的函数都是 外部函数 。 66 【 程序 6有一个字符串 , 内部有若干个字符 , 现输入一个字符 ,要求程序将字符串中该字符删除 。 要求用外部函数实现 。 【 问题分析 】 该 问题可以用如下四个函数解决 。 ( 1) 主函数 ( 2) 输入字符串函数 ( 3) 删除字符函数 ( 4) 输出新字符串函数 以上 四个函数分别放入四个文件 67 /*文件 #*外部函数 (0); /*外部函数 (, /*外部函数 (); c; 0; /*输入字符串 输入待删除的字符: n); %c,&c); c); /*从 c*/ /*输出新字符串 ; 68 /*文件 #*定义外部函数 数 功能 : 输入 字符串送入字符数组 函数 参数 : 字符 数组 数 返回值:空 */ 0) 输入字符串: n); 69 /*文件 #*定义外部函数 数功能: 从字符 数组 数 参数 : 字符 数组 符 数 返回值:空 */ , i,j; i=j=0; i!=0;i+) if(i != j+=i; j=0; 70 /*文件 #*定义外部函数 数 功能 : 输出 新字符串 数 参数 : 字符 数组 数 返回值:空 */ ) 输出新字符串: n); 输入字符串: 输入待删除的字符: c 输出新字符串: 1章 的 1 预处理 命令 : 在 进行编译之前所做的工作 。 预处理命令 源程序 预处理 编译 链接 运行 编译 过程 *处理 命令 均 以 #开头 。 预处理命令 72 宏定义 条件编译 文件包含 73 宏定义 宏定义 : 用 一 个 宏名 ( 标识符 ) 来 表示一个 字符串 。 在 编译预处理时 , 对程序 中 所有出现 的 宏名 都将用 宏定义 中的 字符串代替 。 宏 定义 分为 有 参数 和 无参数 两种 。 1、 无 参数的宏定义 #标识符 字符串 例如: #4 【 程序 6无参数宏的定义和替换 。 # (y*y+3*y) /*无参数宏 () y,请输入 ); %d,&y); *M+4*M+5*M; %dn, ; 无参数的宏定义 *(y*y+3*y)+4*(y*y+3*y)+5*(y*y+3*y); 请 输入 2 120 75 【 程序 6无参数宏的定义和替换 。 #M y*y+3*y /*无参数宏 () y,请输入 ); %d,&y); *M+4*M+5*M; %dn, ; *y*y+3*y+4*y*y+3*y+5*y*y+3*y; 请输入 2 66 无参数的宏定义 76 【 说明 】 如果终止宏定义 的 作用域 可使用 # # #PI 函数 中的 函数 中的 换 无参数的宏定义 77 【 说明 】 若 宏名 在源程序中被 引号 引起来,则预处理程序不对其进行宏替换 。 【程序 6 #K 100 /*无参数宏 () OKn); ; 不替换 无参数的宏定义 78 【程序 6宏定义 的嵌套。 # I *R s=%n,S); ; s=%n, 无参数的宏定义 79 带 参数的宏定义 宏定义 中的参数称为 形式参数 ,宏 调用中的参数称为 实际参数 。 对 带参数的宏进行调用 ,要 用实参去替换形参。 带参数 宏 的 定义 : #宏名 (形参表 ) 字符串 带参数 宏 的 调用: 宏名 (实参表 ); 例如: #M(y) y*y+3*y /*宏定义 */ (2); /*宏调用 */ *2+3*2 80 带 参数的宏定义 【程序 6利用带参数的宏定义计算并输出两个数的最大值。 #a,b) (ab?a:b) /*带参数宏的定义 */ x,y,请输入两个数 x和 y: ); %d%d,&x,&y); AX(x,y); /*带参数宏的调用 */ 最大值是: %dn, ; xy?x:y); 请输入两个数 x和 y: 3 4 最大值是: 4 81 带 参数的宏定义 【说明】 ( 1)在带参数宏定义中,宏名和形参表之间不能有空格。例如,如果把带参数宏的定义: #a,b) (ab?a:b) 写成了: #(a,b) (ab?a:b) AX(x,y); 变成了: a,b) (ab?a:b)(x,y); 表达式 编译无法通过。 82 【说明】 ( 2)带 参宏的定义: #SQ(y) (y)*(y) 带 参宏的调用: Q(2+1); 得到 如下语句: 2+1)*(2+1); 宏 替换中对实参表达式不进行计算,直接照原样替换。 ( 3)带 参宏的定义: #SQ(y) y*y 带 参宏的调用: Q(2+1); 得到 如下语句: +1*2+1; 83 文件包含 # #“ 文件名 ” 前者 是在编译器指定 的 “ 目录内 查找“文件名” 文件。 后者通常 是 表示 在与源文件相同的目录下 查找 “文件名”文件 。 84 同 一目录下 有 *头文件 *源代码文件 # ; ; 给编译器的代码会 变成: ; ; 文件包含 85 条件编译 某些 代码仅在特定的条件成立时才会被编译进可执行文件。这对于程序的移植和调试都是很有用的。 条件编译 有以下 3种形式: ( 1)第一种形式 #标识符 程序段 1 #序段 2 #能 :若标识符已被 #对程序段 1进行编译,否则对程序段 2进行编译。 86 ( 2)第二种形式 #标识符 程序段 1 #序段 2 #能 :若标识符未被 #对程序段 1进行编译,否则对程序段 2进行编译 。 条件编译 ( 3)第三种形式 #常量表达式 程序段 1 #序段 2 #功能 :若常量表达式的值为 真 ,则 对程序段 1进行编译,否则对程序段 2进行编译 。 87 【程序 6输入一个数字,根据需要设置条件编译,输出以该数字为半径的圆的面积或者以该数字为边长的正方形的面积 。 # 1 r,请输入一个正整数: ); %f,&r); # r*r; 圆的面积是: %n, #r*r; 正方形的面积是: %n, #; 请输入一个正整数: 2 圆的面积是: 8 条件编译 条件编译的用武之地? 几乎 所有的大型软件都会用 到 条件编译 。 例如: 很多 软件分为精简版、专业版和豪华版,这样不同配置的版本就是用此方法做到的 。 一些 软件要有跨平台能力,在 不同平台之间有很大差异,有的时候同一件事情在不同平台需要不同的代码来做,条件编译恰好能绝妙地完成这件工

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论