版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
C程序设计一个程序应当是轻盈的、灵活的,它的子程序就像一串珍珠一样连接着。它的精神和意图应该贯穿始终。在程序中,内容既不应太多,也不应太少;既不应该有不需要的循环结构,也不该有冗余的变量;既不缺乏结构性,又不过分僵化。
---GeoffreyJames的《编程之道》
模块化程序设计第5章函数5.1函数的定义5.2函数的调用5.3函数的声明5.4函数参数的传值5.5嵌套调用和递归调用5.6变量的使用范围和存储类别一个C程序可由一个主函数和若干个其他函数(子函数)构成。由主函数调用其他函数,其他函数也可以互相调用,但不能调用主函数。函数分类从用户角度标准函数(库函数):由系统提供用户自定义函数从函数形式无参函数有参函数函数原型intabs(int_X)1、函数功能求绝对值2、函数参数的数目、类型、顺序、意义1个int类型的参数,表示对此参数求绝对值3、函数返回值类型、意义int类型的返回值,表示取绝对值之后的结果4、使用时所需要包含的头文件math.h有一道数学题目:有三个未知数a,b,c,
其中c=f(a,b)=a+b;函数定义的一般形式函数类型,即:函数值(或者称为函数的因变量)的类型。缺省表示int型,无返回值void函数类型
函数名(类型1
形式参数1,类型2
形式参数2,...){
说明部分 语句部分}函数首部或函数头函数体int
f(int
a,intb){ ints;
s=a+b;
returns;}用合法标识符命名,最好见名知意简称形参,指函数中的自变量,是从函数外部向函数内部运送值的数据通道。可根据需要有0到多个。定义时每个形参都应指出各自的类型。
变量说明部分主要是定义运算所需要的变量。因为这些变量在函数内部定义,又称为局部变量。只在函数内部使用有效,不能在函数外部使用。语句部分主要是利用已定义的变量进行运算,得到结果。函数最终需要得到一个结果时,末尾会写return语句。否则可以不写返回语句,此时函数类型应写为void。return是从函数内部向外部传送值的数据通道1.一个函数中可有多个return语句。2.return语句后面可以是变量、常量、表达式,可以用小括号将它括起来。3.若无return语句,遇“}”时,程序自动返回调用函数4.函数类型最好与return语句返回的值类型保持一致。若不一致,函数结果以函数类型为准,由C编译系统自动完成类型转换。【例5.1】用C程序函数实现数学函数f的功能。将数学函数f(a,b)对应写为C程序函数:intf(inta,intb)/*定义函数f,形式参数a,b为整型*/{/*函数f的开始*/ints;/*声明部分,定义本函数中用到的变量s*/s=a+b;/*语句部分,运算求和结果放入s中*/returns;/*将s的值返回给函数f,即:f(a,b)=s;*/}/*函数f的结束找找我是否有错?intf(inta,b){ints;s=a+b;returns;}intf(inta,intb)
{ints;s=a+b;returns;}error找找我是否有错?intf(inta,intb);
{ints;s=a+b;returns;}intf(inta,intb)
{ints;s=a+b;returns;}error找找我是否有错?intf(inta,intb){ints;s=a+b;returns;}intf(inta,intb)
{ints;s=a+b;
returns;}error找找我是否有错?intf(inta,intb){ints;s=a+b;return(s);}intf(inta,intb)
{returna+b;}rightright找找我是否有错?intf(floata,floatb)
{floats;s=a+b;returns;}warning找找我是否有错?intf(inta,intb){if(a>b)returna;elsereturnb;}right良好的习惯:加上函数注释/*函数功能:实现××××功能函数参数:参数1,表示×××××参数2,表示×××××
函数返回值:×××××*/返回值类型
函数名(类型1
形式参数1,类型2
形式参数2,...){
说明部分
语句部分}第5章函数5.1函数的定义5.2函数的调用5.3函数的声明5.4函数参数的传值5.5嵌套调用和递归调用5.6变量的使用范围和存储类别函数定义完毕,需要使用一下,验证函数定义是否正确。使用数学函数f的过程示例:假设有a=3;b=5;将a和b的值代入函数f,求得:
c=f(a,b)=f(3,5)=3+5=8。使用C程序的函数,称为函数调用。函数调用的格式为:函数名(实际参数1,实际参数2,...);实际参数简称实参,可以是常量、变量、表达式,实参的个数、类型应该跟形参一一对应匹配。实参主要用于给形参一一对应传送数据。f(3,5)就是函数调用,其中3和5就是函数的两个整型实参,它们用于给a,b赋值。在主函数中使用f函数:intmain()/*主函数*/{intc;/*定义存放结果的变量*/
c=f(3,5);/*调用函数f,将得到的值赋给c*/printf(“c=%d\n”,c);/*输出c的值*/return0;}标记了执行顺序的完整程序如下:#include<stdio.h>intf(inta,intb)/*定义函数f*/{ ints;s=a+b;returns;}intmain()/*定义主函数*/{intc;c=f(3,5);/*调用函数f*/printf("c=%d\n",c);return0;}56789101234121314给形参分配内存实参传值给形参11将结果传回给函数f(3,5)=s;撤销形参的内存使用函数调用的形式(1)函数调用作为一条语句;(2)函数有明确的返回值时,函数调用可以当做普通变量使用,作为表达式的一部分。(3)函数有明确的返回值时,函数调用可以作为其他函数的实参。【例5.2】编写函数实现打印以下图形的功能。若函数不需要从外界获取值,可以不写参数。函数本身不需要一个计算结果,将函数类型设为void类型,函数结尾不需要写return语句。调用这类函数时,直接将调用加上分号,作为一条语句。若将其作为表达式的一部分,例如:inta=printStar();程序出错。修改函数,将其功能扩展为可输出n行此图形用这种格式,可以吗?实参和形参个数不一致,严格的编译器会报错,VC6.0可以执行,但无输出结果。也正确,但不通用,每次需要输出不同行的图形时都要修改函数。【例5.3】定义pow函数,实现求xy的功能。只考虑x和y均为正整数的情况。
调用函数pow作为了printf函数中用于输出的第3个参数。可以去掉参数吗?若需要计算用户从键盘输入的x和y的幂次方,如何修改程序?将变量a和b作为实参,它们的值由用户从键盘输入注意:不要写成pow(inta,intb)【例5.4】定义bigger函数,实现求两个整数中较大值的功能。利用此函数求三个整数中的较大值。
函数调用时,形参若是变量,只写变量名,不写变量的类型。例如:将bigger(x,y)写为bigger(intx,inty)是错误的。实参x和y在函数调用前已经有定义了,不能在此处再定义。bigger(bigger(x,y),z)作为了赋值表达式max=bigger(bigger(x,y),z)的一部分,即:函数调用可以作为表达式的一部分。第5章函数5.1函数的定义5.2函数的调用5.3函数的声明5.4函数参数的传值5.5嵌套调用和递归调用5.6变量的使用范围和存储类别将例题5-1程序中自定义函数f和main函数的位置互换,执行程序,观察实验结果。
在程序运行前的编译阶段,要进行语法检错。程序编译的顺序是按照代码书写的先后顺序来顺次编译的。当编译到函数调用语句时,由于还未编译到函数定义的部分,因此C编译系统不知道后面是否有此函数的定义,也不知道此函数调用格式是否正确,所以C编译系统会提示找不到函数。为了解决这个问题,可以在函数调用前面加上函数声明。函数声明:函数的使用说明书函数声明由函数首部加上分号组成。例如:函数f的函数声明为:intf(inta,intb);也可以将参数名省略:intf(int,int);。说明:(1)加上形参名的格式更清楚些。(2)若函数定义在函数调用前面,则不需要添加函数声明。【例5.5】函数声明的使用。第5章函数5.1函数的定义5.2函数的调用5.3函数的声明5.4函数参数的传值5.5嵌套调用和递归调用5.6变量的使用范围和存储类别一、单向值传递【例5.6】写一个函数实现两个整数的交换,测试main
swap05xyab50c050当基本类型的常量或变量作函数的实参时,形参与实参占用不同的内存空间(可同名)。从实参到形参的数据传递是单向的。即:形参值的改变不会影响到实参,这称为“单向值传递”。
二、双向地址传递当地址常量或地址变量(例如:数组名)作函数的实参时,从实参到形参传递的是地址,形参与实参使用相同的内存空间。形参值的改变会影响到实参,这种传递也称为“双向地址传递”。例如:void
BubbleSort(inta[10]){//对数组a的元素按冒泡法排序}intmain(){intb[10]={7,1,4,2,9,0,8,5,-3,2};BubbleSort(b);//b是数组名,进行地址传递}形参a不另外分配内存,它就使用b数组的内存,可将a,b看成同一个数组,对a排序,即是对b排序,所以调用函数BubbleSort后,数组b内的元素已排好序。还可写为:void
BubbleSort(inta[])
【例5.7】有一个已按由小到大的顺序排列的整型数组,从键盘输入一个整数,按照数组原来的排列规律将此数插入到数组中。写一个函数insertNumber实现此功能,并测试。思路:1.若num大于或者等于a[8],例如:num是99,那么直接将num存入arr[9]中即可。2.否则,例如:num是20,先查找num应该放在数组中哪个位置。再将此位置及后面的数据依次后移,最后将num存入此位置中。①查找位置:②在将num放入a[3]之前,先将a[8]、a[7]、...、a[4]、a[3]依次后移。③将num赋值给a[3]。
第5章函数5.1函数的定义5.2函数的调用5.3函数的声明5.4函数参数的传值5.5嵌套调用和递归调用5.6变量的使用范围和存储类别一、嵌套调用一个函数调用另一个函数,另一个函数又调用其他函数,称为函数的嵌套调用。C规定函数定义不可嵌套,但可以嵌套调用函数。【例5.8】编写程序计算s=1!+2!+3!+...+n!调用调用嵌套调用二、递归调用一个函数直接调用自己本身或者通过调用其他函数来间接地调用自己,称为递归函数。【例5.9】递归问题:有5个人坐在一起,问第5个人多少岁?他说比第4个人大5岁。问第4个人岁数,他说比第3个人大5岁。问第3个人,又说比第2个人大5岁。问第2个人,说比第1个人大5岁。最后问第1个人,他说他10岁。请问第5个人多大?
根据题目中给出的年龄关系,列出计算第n个人年龄的数学公式:根据数学公式,写出对应的C函数如下:intage(intn){if(n==1){ /*递归结束条件成立,结束递归*/ return10;}else{/*递归结束条件不成立,继续进行递归调用*/ returnage(n-1)+5;}}或者:intage(intn){if(n>1){/*递归结束条件不成立,继续进行递归调用*/returnage(n-1)+5;}else{ /*递归结束条件成立,结束递归调用*/return10;}}年龄的递归运算过程【例5.10】用递归调用求n的阶乘。第5章函数5.1函数的定义5.2函数的调用5.3函数的声明5.4函数参数的传值5.5嵌套调用和递归调用5.6变量的使用范围和存储类别一、局部变量与全局变量局部变量(也称为内部变量):在函数内部定义,有效使用范围是从定义处开始,到本函数结束为止。全局变量(也称为外部变量):在函数外部定义,不作特殊声明的情况下,有效使用范围是从定义处开始,到所在源文件末尾为止。例如:两个n不是同一个变量,可以同名【例5.11】局部变量的有效区域。局部变量a和b的有效范围超出此范围使用它们会出错【例5.12】全局变量的有效区域。全局变量a和b定义函数外部,有效范围从定义处开始,到所在源文件结束为止。【例5.13】不同函数中的同名局部变量。fun中a和b的有效范围main中a和b的有效范围【例5.14】局部变量和全局变量同名。局部变量a和b的有效范围全部变量a和b的有效范围二、变量的存储类别一个变量完整的定义中除了变量的数据类型之外,还应加上存储类型的限制。格式如下:
[存储类型]
数据类型变量名;C语言中,变量的存储类型可以分为四类:auto(自动型)、static(静态型)、register(寄存器型)、extern(外部型)。不同类型的变量的生命周期(指的是在程序运行过程中,变量从创建到撤销的一段时间)不同。1、auto类型的局部变量函数形参和局部变量,不加任何修饰时,默认为auto类型的局部变量。这类变量生命周期与其所在的函数代码块共存亡。即:函数调用开始时给变量分配动态内存空间。函数结束时,释放内存,变量的生命周期终止。生命周期与有效范围一致。【例5.15】局部变量的生命周期。2、static类型的局部变量、全局变量static修饰的全局变量和局部变量分别称为静态全局变量和静态局部变量。这类变量生命周期与程序共存亡。在程序开始执行前给它们分配内存,程序执行完毕时释放内存。在程序执行过程中它们占据固定的存储空间。生命周期是到整个程序结束,有效范围是到所在的源文件结束。【例5.16】静态局部变量的生命周期。3、全局变量普通的全局变量存放在内存中的静态存储区,生命周期到整个程序结束。它的有效范围可以通过将其声明为extern类型扩展到整个程序结束。【例5.17】全局变量的生命周期和有效区域。同一个项目中有两个源文件test1.c、test2.c。运行test2.c文件,出错。虽然全局变量A的生命期是整个程序,在整个程序中都占有内存,但是它的有效区域是test1.c文件,在test2.c文件中不能使用test1.c文件。4、extern类型的全局变量extern类型的全局变量存放在内存中的静态存储区,生命周期到整个程序结束,它的有效范围是到整个程序结束,两者一致。【例5.18】extern类型全局变量的生命周期和
有效区域。同一个项目中有两个源文件test1.c、test2.c。运行test2.c文件,输出0。扩展也可以写为“externA;”,这是test1.c中定义的全局变量A的有效区域扩展到test2.c文件中。若未给全局变量赋初值,内存空间中的值为0。【例5.19】用extern扩展static类型全局变量的有效区域。运行test2.c文件,程序出错。静态全局变量A的
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026事业单位工勤技能-江苏-江苏机械热加工三级(高级工)历年参考题库含答案详解3套试卷
- 2026事业单位工勤技能-江苏-江苏农业技术员三级(高级工)历年参考题库含答案详解3套试卷
- 2026事业单位工勤技能-新疆-新疆理疗技术员五级(初级工)历年参考题库含答案详解3套试卷
- 2026事业单位工勤技能-广西-广西食品检验工二级(技师)历年参考题库含答案详解3套试卷
- 2026 年读懂气象预警防范次生地质灾害
- 消防安全生产考核情况分析
- 2026年秋季开学高三体育放松心理减压课件
- 2026年秋季开学初二新学期学习规划课件:论文写作
- 2026年秋季开学大学一年级新生军训家长寄语教育课件
- 2026年甘肃公安局出纳招聘考试练习试卷【含答案】
- 招聘消防文员试题及答案
- 湿热灭菌器以及湿热灭菌工艺的验证
- 安全管理人员七大职责
- JGJT46-2024《施工现场临时用电安全技术标准》条文解读
- 教学常规管理培训课件
- 走进管理智慧树知到期末考试答案章节答案2024年中国海洋大学
- 矿山机电管理培训课件
- 口腔医院客服培训课件
- 卫生监督协管培训公共场所知识培训医学课件
- 房屋加装电梯施工项目施工组织设计方案
- 通止规标准计算表
评论
0/150
提交评论