已阅读5页,还剩86页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
模块化程序设计基本思想 将一个大的程序按功能分割成一些小模块 特点 各模块相对独立 功能单一 结构清晰 接口简单控制了程序设计的复杂性提高元件的可靠性缩短开发周期避免程序开发的重复劳动易于维护和功能扩充 第六章函数 C是模块化程序设计语言 C程序结构 C是函数式语言必须有且只能有一个名为main的主函数C程序的执行总是从main函数开始 在main中结束函数不能嵌套定义 可以嵌套调用 例 在C程序中 函数既可以嵌套定义 也可以嵌套调用 函数分类从用户角度标准函数 库函数 由系统提供用户自定义函数从函数形式无参函数有参函数 使用库函数应注意 1 函数功能2 函数参数的数目和顺序 及各参数意义和类型3 函数返回值意义和类型4 需要使用的包含文件 Ch7 201 c 6 1函数一 函数的定义一般格式 合法标识符 函数返回值类型缺省int型无返回值void 函数体 例有参函数 现代风格 intmax intx inty intz z x y x y return z 例无参函数printstar printf n 或printstar void printf n 返回语句形式 return 表达式 或return表达式 或return 功能 使程序控制从被调用函数返回到调用函数中 同时把返值带给调用函数说明 函数中可有多个return语句若无return语句 遇 时 自动返回调用函数若函数类型与return语句中表达式值的类型不一致 按前者为准 自动转换 函数调用转换void型函数 例无返回值函数voidswap intx inty inttemp temp x x y y temp 例 编写程序 输入一个正整数n 求下列算式的值 要求定义和调用函数fact k 计算k的阶乘 函数返回值的类型是double 2006年春试题 doublefact intk doubles 0 inti t 1 for i 1 i k i t t i s s 1 0 t returns 二 函数的调用调用形式函数名 实参表 说明 实参与形参个数相等 类型一致 按顺序一一对应实参表求值顺序 因系统而定 TurboC自右向左 includemain intn doublesum scanf d 调用方式函数语句 例printstar printf Hello World n 函数表达式 例m max a b 2 函数参数 例printf d max a b m max a max b c main inti 2 j 2 p p f i j printf d p intf inta intb intc if a b c 1 elseif a b c 0 elsec 1 return c 例参数求值顺序 运行结果 0 调用函数语句1 主调函数 主调函数 Return语句或最后一个 执行函数调用的内涵 1 把实参的值传给形参 2 把控制语句传给被调函数 也就是说程序的执行由主调函转到被调函数 3 在函数中执行return语句 将返回值带回到主调函数 printstar printf main inta a printstar printf d a 例函数带回不确定值 输出 10 voidprintstar printf main inta a printstar printf d a 编译错误 例函数返回值类型转换 main floata b intc scanf f f 三 函数参数及其传递方式形参与实参形式参数 定义函数时函数名后面括号中的变量名实际参数 调用函数时函数名后面括号中的表达式 例比较两个数并输出大者 main inta b c scanf d d 说明1 实参必须有确定的值形参必须指定类型形参与实参类型一致 个数相同若形参与实参类型不一致 自动按形参类型转换 函数调用转换形参在函数被调用前不占内存 函数调用时为形参分配内存 调用结束 内存释放 形参与实参形式参数 定义函数时函数名后面括号中的变量名实际参数 调用函数时函数名后面括号中的表达式 说明2 1 形参只有在函数调用时才分配存储单元 调用结束后 释放所分配的单元 2 实参可以是常量 变量 表达式 总之要有确定的值 当函数调用时 将实参的值传递给形参 若是数组名 则传送的是数组的首地址 3 被调函数中 形参类型必须指定 以便分配存储单元 4 实参 形参的数据类型一致 赋值要兼容 顺序要一致 5 若被调函数类型为非整形 要在主调函数中对被调函数作原形声明或在主调函数之前定义 6 实参对形参的数据传送是值传送 也是单向传送 当被调函数的形参发生变化时 并不改变主调函数实参的值 例计算x的立方 includefloatcube floatx return x x x main floata product printf Pleaseinputvalueofa scanf f x 1 2 1 728 1 参数传递方式值传递方式方式 函数调用时 为形参分配单元 并将实参的值复制到形参中 调用结束 形参单元被释放 实参单元仍保留并维持原值特点 形参与实参占用不同的内存单元单向传递 例交换两个数 ch7 2 c includemain intx 7 y 11 printf x d ty d n x y printf swapped n swap x y printf x d ty d n x y swap inta intb inttemp temp a a b b temp 函数说明对被调用函数要求 必须是已存在的函数库函数 include用户自定义函数 函数类型说明函数说明一般形式 函数类型函数名 形参类型 形参名 或函数类型函数名 作用 告诉编译系统函数类型 参数个数及类型 以便检验函数定义与函数说明不同函数说明位置 程序的数据说明部分 函数内或外 下列情况下 可不作函数说明若函数返值是char或int型 系统自动按int型处理被调用函数定义出现在主调函数之前有些系统 如BorlandC 要求函数说明指出函数返值类型和形参类型 并且对void和int型函数也要进行函数说明 例函数说明举例 二 地址传递方式 函数调用时 将数据的存储地址作为参数传递给形参特点 形参与实参占用同样的存储单元 双向 传递实参和形参必须是地址常量或变量方法有两种指针作函数的参数数组作函数的参数 1 指针作函数的参数 1 用指针 地址 作函数参数 可以实现 通过被调用的函数改变主调函数中变量的值 的目的 2 使用指针作为函数参数可以在调用一个函数时得到多个由被调函数改变了的值 ch9 3 c swap int p1 int p2 intp p p1 p1 p2 p2 p main inta b scanf d d 例交换两个数 例如 有一数组有10个元素 要求输出其中最大和最小的元素值 defineN10main voidmax min intarr int pt1 int pt2 intn intarray N 1 8 10 2 5 0 7 15 4 5 p1 p2 a b p1 函数的嵌套与递归调用 加 嵌套调用C规定 函数定义不可嵌套 但可以嵌套调用函数 例求三个数中最大数和最小数的差值 includeintdif intx inty intz intmax intx inty intz intmin intx inty intz voidmain inta b c d scanf d d d Ch7 202 c intdif intx inty intz returnmax x y z min x y z intmax intx inty intz intr r x y x y return r z r z intmin intx inty intz intr r x y x y return r z r z 例用弦截法求方程根 运行情况 Inputx1 x2 2 6 Arootofequationis5 0000 递归调用定义 函数直接或间接的调用自身叫函数的递归调用 说明C编译系统对递归函数的自调用次数没有限制每调用函数一次 在内存堆栈区分配空间 用于存放函数变量 返回值等信息 所以递归次数过多 可能引起堆栈溢出 intf intx inty z z f y return 2 z 例求n的阶乘 ch7 8 c includeintfac intn intf if n 0 printf n 0 dataerror elseif n 0 n 1 f 1 elsef fac n 1 n return f main intn y printf Inputaintegernumber scanf d 例1 函数f定义如下 执行语句 m f 5 后 m的值应为 intf intk if k 0 k 1 return1 elsereturnf k 1 f k 2 A 3B 8C 5D 13 例2 对于以下递归函数f 调用函数f 2 1 2 3 的输出结果是 Voidf intn chara charb charc if n 1 printf c c a b else f n 1 a c b printf c c a b f n 1 c b a A 1 1 3 3 2 B 3 2 1 2 1 3 C 1 3 3 2 1 2 D 1 3 1 2 3 2 6 2函数参数一 数组元素作函数实参 值传递 例两个数组大小比较 n 0m 0k 0 a和b为有10个元素的整型数组比较两数组对应元素变量n m k记录a i b i a i b i a i k 认为数组a b若n k 认为数组a b若n k 认为数组a b 数组名作函数参数地址传递在主调函数与被调函数分别定义数组 且类型应一致形参数组大小 多维数组第一维 可不指定形参数组名是地址变量 例求学生的平均成绩 includefloataverage intstu 10 intn voidmain intscore 10 i floatav printf Input10scores n for i 0 i 10 i scanf d floataverage intstu 10 intn inti floatav total 0 for i 0 i n i total stu i av total n returnav 实参用数组名 形参用数组定义 intstu 例数组元素与数组名作函数参数比较 includevoidswap2 intx inty intz z x x y y z main inta 2 1 2 swap2 a 0 a 1 printf a 0 d na 1 d n a 0 a 1 值传递 includevoidswap2 intx intz z x 0 x 0 x 1 x 1 z main inta 2 1 2 swap2 a printf a 0 d na 1 d n a 0 a 1 地址传递 例数组元素与数组名作函数参数比较 例数组排序 简单选择排序 9 49 i 0 例数组排序 简单选择排序 13 68 i 1 i 8 例数组排序 简单选择排序 例求二维数组中最大元素值 intmax value intarray 3 4 inti j k max max array 0 0 for i 0 imax max array i j return max main inta 3 4 1 3 5 7 2 4 6 8 15 17 34 12 printf maxvalueis d n max value a 例求二维数组中各行元素之和 get sum row intx 3 intresult introw intcol inti j for i 0 i row i result i 0 for j 0 j col j result i x i j main inta 2 3 3 6 9 1 4 7 intsum row 2 row 2 col 3 i get sum row a sum row row col for i 0 i row i printf Thesumofrow d d n i 1 sum row i 18 12 几点说明 1 数组名作形 实参数时 应分别在主 被调函数中对其声明2 形 实参数的数组类型要一致 大小一般相等 以保证数据的全部传送 3 当形参数组大小未指定时 用一实参将数组长度传递给形参以便对数组进行操作 4 数组名作参数时 传递的是地址 对形参数组的操作实际上也是对实参数组的操作 6 2 2字符串指针作函数参数 将一个字符串从一个函数传递到另一个函数 可以采用地址传递的办法 即将字符数组名作参数或用指向字符串的指针变量作参数 在被调用的函数中可以改变字符串的内容 在主调函数中可以得到改变了的字符串 voidcopy string from to charfrom to inti 0 while from i 0 to i from i i to i 0 main chara Iamateacher charb youareastudent printf string a s nstring b s n a b copy string a b printf nstring a s nstring b s n a b 1 形参和实参都用用字符数组作参数 程序 voidcopy string from to char from to for from 0 from to to from to 0 main chara Iamateacher charb youareastudent printf string a s nstring b s n a b copy string a b printf nstring a s nstring b s n a b 2 形参用字符指针变量 实参用数组名 另外形参和实参都用字符指针 以及形参用字符数组名 实参用字符指针在10 3 2中已经讲过 不再重复 3 copy string函数的简化 6 3函数指针 一个函数包括一组指令序列 存储在某一段内存中 这段内存空间的起始地址称为函数的入口地址称函数入口地址为函数的指针 函数名代表函数的入口地址可以定义一个指针变量 其值等于该函数的入口地址 指向这个函数 这样通过这个指针变量也能调用这个函数 这种指针变量称为指向函数的指针变量 定义指向函数的指针变量的一般形式为 类型标识符 指针变量名 例 int p 指针变量p可以指向一个整型函数 float q 指针变量q可以指向一个浮点型函数 下一页 上一页 刚定义的指向函数的指针变量 亦象其它指针变量一样要赋以地址值才能引用 当将某个函数的入口地址赋给指向函数的指针变量 就可用该指针变量来调用所指向的函数给函数指针赋初值 将函数名 函数的入口地址值 赋给指针变量例如intm p intmax inta intb 则可以p max p指向函数max 指针调用函数的一般形式为 指针变量 实参表 如上例 m p 12 22 比较m max 12 22 下一页 上一页 用函数指针调用函数是间接调用 没有参数类型说明 C编译系统也无法进行类型检查 因此 在使用这种形式调用函数时要特别小心 实参一定要和指针所指函数的形参类型一致 函数指针可以作为函数参数 此时 当函数指针每次指向不同的函数时 可执行不同的函数来完成不同的功能 下一页 上一页 注意 例函数max 用来求一维数组的元素的最大值 在主调函数中用函数名调用该函数与用函数指针调用该函数来实现 下一页 上一页 include stdio h defineM8main floatsumf sump floata M 11 2 3 4 5 5 69 7 80 float p 定义指向函数的指针p floatmax floata intn 函数声明 p max 函数名 函数入口地址 赋给指针p sump p a M 用指针方式调用函数 sumf max a M 用函数名调用max 函数 printf sump 2f n sump printf sumf 2f n sumf floatmax floata intn intk floats s a 0 for k 0 k n k if s a k s a k returns 下一页 上一页 程序运行结果 sump 80 00sumf 80 00 1 定义一个指向函数的指针变量 形如 float p 2 为函数指针赋值 格式如下 p 函数名 注意 赋值时只需给出函数名 不要带参数 3 通过函数指针调用函数 调用格式如下 s p 实参 上一页 指向函数的指针的使用步骤 返回 函数指针的作用 用函数指针变量作函数的参数函数的参数既可以是变量 常量 指针变量 数组名 数组指针变量 也可以是函数指针或函数指针变量 以便实现函数地址的传送 达到用某个函数调用其他的函数 函数的调用方式 1 直接使用函数名2 间接调用 通过函数指针 0 Y X h f b f a n h b a f a 共n等份 f x h b a n f a h f a n 1 h s 1 x2 floatf1 x floatx floatf f 1 x x return f floatf3 x floatx floatf f x 1 x x return f 1 x x2 x3 floatf2 x floatx floatf f 1 x x x x x x return f 多层间接调用 即用函数指针变量作函数的参数 在调用一个通用函数时 便于处理多种情况 以便选用各种专用的函数 这样做的好处是使得程序通用性强 结构模块化程度高 例 求不同被积函数的积分 1 x2 floatintegral fun a b float fun a b floats h y intn i s fun a fun b 2 0 n 100 h b a n for i 1 i n i s s fun a i h y s h return y 梯形法求解定积分 main floatf1 f2 f3 integral floaty1 y2 y3 y1 integral f1 0 0 1 0 y2 integral f2 0 0 2 0 y3 integral f3 0 0 3 5 printf y1 6 2f ny2 6 2f ny3 6 2f n y1 y2 y3 S h f a f b 2 f a h f a 2h f a n 1 h 由上述例子可以看出 首先函数integral fun a b 是用梯形法求积分的通用函数 它适用于各种被积函数 f1 f2 f3为三个不同的被积函数 如果要用integral函数求解其它的被积函数的定积分 则只要添加相应的被积函数的构造函数 而无须改写或重新编写integral函数 在主调函数中直接调用integral函数 当然要提供相应的参数 即可 如果把被积函数的构造和求积分的函数写在一起 那就不具备通用性了 注意 main 函数中的floatf1 f2 f3 integral 语句不能省略 这一句告诉系统f1 f2 f3是函数 而不是变量 6 4指针型函数 返回指针的函数 下一页 上一页 指针函数 是指返回值为指针的函数指针函数的定义形式 类型标示符 函数名 参数 例如 int fun inta intb 函数体语句 在函数体中有返回指针或地址的语句 形如 return 并且返回值的类型要与函数类型一致 例分析如下程序 main inta b p int max intx inty scanf d d int max intx inty ifx y return 下一页 上一页 6 5命令行参数 在操作系统命令状态下 可以输入程序或命令使其运行 称命令行状态 输入的命令 或运行程序 及该命令 或程序 所需的参数称为命令行参数 如 copyfdfscopy是文件拷贝命令 fd fs是命令行参数 main函数是可以有参数的 但与普通函数不同 带形参的main 函数的一般形式是 main intargc char argv 形参argc记录命令行中字符串的个数 argv是一个字符型指针数组 每一个元素顺序指向命令行中的一个字符串 下一页 上一页 1 main 函数的形参与实参 main 函数由系统自动调用 而不是被程序内部的其它函数调用 main 函数所需的实参不可能由程序内部得到 而是由系统传送 main 函数所需的实参与形参的传递方式也与一般函数的参数传递不同 实参是在命令行与程序名一同输入 程序名和各实际参数之间都用空格分隔 格式为 执行程序名参数1参数2 参数n形参argc为命令行中参数的个数 包括执行程序名 其值大于或等于1 而不是象普通C语言函数一样接受第一个实参 形参argv是一个指针数组 其元素依次指向命令行中以空格分开的各字符串 即 第一个指针argv 0 指向程序名字符串 argv 1 指向参数1 argv 2 指向参数2 argv n 指向参数n 下一页 上一页 2 命令行参数的传递示例例8 11分析下列程序 指出其执行结果 该程序命名为exam c 经编译连接后生成的可执行程序为exam exe includemain intargc char argv inti 0 printf argc d n argc while argc 1 printf n参数 d s i argv i argc argv 下一页 上一页 输出结果 argc 4参数0 exam参数1 Turbo c参数2 C 参数3 Vc程序开始运行后 系统将命令行中字符串个数送argc 将四个字符串实参 exam Turbo c C Vc的首地址分别传给字符指针数组元素argv 0 argv 1 argv 2 argv 3 若运行该程序时的命令行输入的是 examTurbo cC Vc 上一页 返回 6 6变量的存储属性概述变量是对程序中数据的存储空间的抽象 编译或函数调用时为其分配内存单元 10 程序中使用变量名对内存操作 变量的属性数据类型 变量所持有的数据的性质 操作属性 存储属性存储器类型 寄存器 静态存储区 动态存储区生存期 变量在某一时刻存在 静态变量与动态变量作用域 变量在某区域内有效 局部变量与全局变量变量的存储类型auto 自动型register 寄存器型static 静态型extern 外部型变量定义格式 存储类型 数据类型变量表 概述变量是对程序中数据的存储空间的抽象 如 intsum autointa b c registerinti staticfloatx y 局部变量与全局变量局部变量 内部变量定义 在函数内定义 只在本函数内有效说明 main中定义的变量只在main中有效不同函数中同名变量 占不同内存单元形参属于局部变量可定义在复合语句中有效的变量局部变量可用存储类型 autoregisterstatic 默认为auto 全局变量 外部变量定义 在函数外定义 可为本文件所有函数共用有效范围 从定义变量的位置开始到本源文件结束 及有extern说明的其它源文件 应尽量少使用全局变量 因为 全局变量在程序全部执行过程中占用存储单元降低了函数的通用性 可靠性 可移植性降低程序清晰性 容易出错 定义说明次数 只能1次可说明多次位置 所有函数之外函数内或函数外分配内存 分配内存 可初始化不分配内存 不可初始化 外部变量说明 extern数据类型变量表 外部变量定义与外部变量说明不同 若外部变量与局部变量同名 则外部变量被屏蔽 外部变量可用存储类型 缺省或static floatmax min floataverage floatarray intn inti floatsum array 0 max min array 0 for i 1 imax max array i elseif array i min min array i sum array i return sum n main inti floatave score 10 Input ave average score 10 printf max 6 2f nmin 6 2f naverage 6 2f n max min ave externcharc1 c2 externcharc1 c2 运行结果 max 13 externinta b intmax intz z a b a b return z main printf max d max inta 13 b 8 运行结果 max 8 inti main voidprt for i 0 i 5 i prt voidprt for i 0 i 5 i printf c printf n 例外部变量副作用 运行结果 动态变量与静态变量存储方式静态存储 程序运行期间分配固定存储空间动态存储 程序运行期间根据需要动态分配存储空间内存用户区 生存期静态变量 从程序开始执行到程序结束动态变量 从包含该变量定义的函数开始执行至函数执行结束 1 auto变量函数内部无static声明的局部量均为动态存储类别 被分配在动态区 存储类别为自动时 声明符auto可省 自动变量被分配在动态区 未赋初值时 其值未定义 每次调用重新赋值 intf inta autointb c 3 定义b c为自动变量 又如 autointb c 3 intb c 3 两者等价 2 用static声明局部变量若希望函数调用结束后 其值不消失 下次调用函数时继续使用 则用static对变量加以声明 例考察静态局部变量的值f inta autointb 0 staticintc 3 b b 1 c c 1 return a b c main inta 2 i for i 0 i 3 i printf d f a 运行结果 789 静态局部变量的声明 1 分配在静态区 程序运行结束释放存储单元 2 仅开始时赋初值一次 未赋初值时为0 以后每次调用函数时 变量不再赋值 前次操作的结果被保留 3 局部动态变量若未赋初值 其值是不确定的 所分配的存储单元是不固定的 而局部静态变量未赋初值 其值为0 字符型变量的值为 0 所分配的存储单元是固定的 4 静态局部变量在函数调用结束后虽存在 但其它函数不能引用它 使用局部静态变量有如下几种情况 1 需要保留上一次调用结束时的值 2 初始化后变量只被引用而不改变其值 则用静态局部变量较方便 缺点 从程序运行开始到结束一直占用内存 这样会浪费系统资源 例打印1 5的阶乘值intfac intn staticintf 1 f f n return f main inti for i 1 i 5 i printf d d n i fac i 问题 1 将static改为auto2 其它函数能否使用局部静态变量 f inta autointb 0 staticintc 3 b b 1 c c 1 printf f main 026ff 01famain a ffd8 a 2main i ffda i 252f a ffd6 a 2f b ffd0 b 1f c 0194 c 47f a ffd6 a 2f b ffd0 b 1f c 0194 c 58f a ffd6 a 2f b ffd0 b 1f c 0194 c 69 3 register变量CPU内部有寄存器组可用来存放数据 若把数据声明为寄存器类型 则将该类型的数据存放在寄存器中 其优点在于 减少数据与内存之间的交换频率 提高程序的效率和速度 例使用寄存器变量intfac intn registerinti f 1 for i 1 i n i f f i return f main inti for i 1 i 5 i printf d d n i fac i 运行结果 1 12 23 64 245 120 4 用extern声明外部变量外部变量也称全局变量 在函数外部定义 其作用域是从变量的定义处开始 到本程序文件的未尾 5 用static声明外部变量若使全局变量只限于定义它的文件中的函数引用 而不让其它文件中的函数引用 需要用static加以说明 注意 此种说法只在工程方法中有效 而在文件包含中则不起作用 关于作用域和生成期的概念用图例说明变量的作用域和生成期的关系 关于作用域和生成期的概念用图例说明变量的作用域和生成期的关系 变量存储类型小结 局部变量默认为auto型register型变量个数受限 且不能为long double float型局部stati
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 执业护士实践能力真题2018年及答案解析
- 执业药师继续教育答案
- 执业药师考试药学知识二试题及答案
- 教师招聘考试试题及答案(一)
- 2025 年大学林学(林业技术推广)试题及答案
- 施工员考试试题及答案(卷一)
- 月嫂初级考试题及答案
- 母婴护理员模拟试题
- 车祸复合伤应急预案(3篇)
- 2025年劳动仲裁纠纷题库及答案
- 【MOOC答案】《3D工程图学》(华中科技大学)章节作业慕课答案
- 《工业战略性新兴产业分类目录(2023)》
- 普通硅酸盐水泥-硫铝酸盐水泥复合胶凝体系混凝土的性能研究
- 连续性肾脏替代疗法
- 1.工程建设前期法定建设程序检查表GD1701
- 钢结构加工安装合同 钢结构构件加工合同(3篇)
- GB/T 16674.1-2004六角法兰面螺栓小系列
- 涡轮风扇发动机原理
- 中药材的采收与产地加工课件
- 运动前评价课件
- 我国玉米深加工产业概述课件
评论
0/150
提交评论