1、第第6 6章章 函函 数数第1页目标目标l描述描述 C C 语言中函数语言中函数l掌握掌握 C C 语言中常见内置函数语言中常见内置函数l了解函数原型和函数返回值了解函数原型和函数返回值l熟练掌握自定义函数定义和调用熟练掌握自定义函数定义和调用l了解变量作用域、生命期l了解变量存放类型正确了解函数在正确了解函数在C C语言程序设计中作用和地位;语言程序设计中作用和地位;了解函数、形参、实参、作用域、生存期概念;了解函数、形参、实参、作用域、生存期概念;掌握各种函数定义、原型申明和调用方法;掌握各种函数定义、原型申明和调用方法;了解全局变量、局部变量、静态变量、静态函数作用域了解全局变量、局部变
2、量、静态变量、静态函数作用域和生存期;和生存期;掌握递归函数编写规则;掌握递归函数编写规则;掌握利用工程管理程序方法;掌握利用工程管理程序方法;第2页u6.1.1 6.1.1 什么是模块化什么是模块化 模块化程序设计方法:模块化程序设计方法:人们在求解某个复杂问题时,通常采取人们在求解某个复杂问题时,通常采取逐步分逐步分解、分而治之解、分而治之方法,也就是将一个大问题分解成若方法,也就是将一个大问题分解成若干个比较轻易求解小问题,然后分别求解。程序员干个比较轻易求解小问题,然后分别求解。程序员在设计一个复杂应用程序时,往往也是把整个程序在设计一个复杂应用程序时,往往也是把整个程序划分成若干个功
3、效较为单一程序模块,然后分别给划分成若干个功效较为单一程序模块,然后分别给予实现,最终再把全部程序模块象搭积木一样装配予实现,最终再把全部程序模块象搭积木一样装配起来,这种在程序设计中分而治之策略,被称为模起来,这种在程序设计中分而治之策略,被称为模块化程序设计方法。块化程序设计方法。6.1 6.1 概述概述第3页maincabdefghijkl图6-1 C程序模块化C C程序模块化程序模块化第4页6.1.2 6.1.2 什么是函数?什么是函数?l在在C C语言中,模块就是一组逻辑相关语言中,模块就是一组逻辑相关(这也表达这也表达了软件工程中了软件工程中“内聚性内聚性”)语句集合或说是用于语句
4、集合或说是用于完成特定任务程序代码单元。完成特定任务程序代码单元。l依据规模大小,依据规模大小,C C语言中模块有三种形式:语言中模块有三种形式:语句块(即复合语句)语句块(即复合语句)函数函数文件。文件。函数是函数是C C语言中最为惯用模块单元。语言中最为惯用模块单元。所以通常说所以通常说C C程序是由函数组成;程序是由函数组成;函数是函数是C C语言程序基本组成部分。语言程序基本组成部分。第5页void main():x=x*x*x;y=y*y*y;z=z*z*z;ans1=x+y+z;a=a*a*a;b=b*b*b;c=c*c*c;ans2=a+b+c;:重复屡次同一计算类型void m
5、ain():ans1=cube(x,y,z);ans2=cube(a,b,c);:int cube(int a,b,c)int ans;ans=(a*a*a)+(b*b*b)+(c*c*c);return ans;函数函数主程序主程序ans函数能够把相对独立某个功效抽象出来,使之成为函数能够把相对独立某个功效抽象出来,使之成为程序中一个独立实体。能够在同一个程序或其它程程序中一个独立实体。能够在同一个程序或其它程序中屡次重复使用序中屡次重复使用为何使用函数?为何使用函数?第6页l使程序变得更简短而清楚使程序变得更简短而清楚 l有利于程序维护有利于程序维护l能够提升程序开发效率能够提升程序开发效
6、率 l提升了代码重用性提升了代码重用性 函数机制优点函数机制优点第7页6.2.16.2.1 函数分类函数分类 内置函数(库函数):内置函数(库函数):由语言系统提供;由语言系统提供;用户无须定义,也无须用户无须定义,也无须在程序中作类型说明;在程序中作类型说明;只需在程序前包含有该只需在程序前包含有该函数定义头文件函数定义头文件;自定义函数:自定义函数:用户在程序中依据需用户在程序中依据需要而编写函数要而编写函数;l从用户角度6.2 6.2 函数定义与使用函数定义与使用第8页内置函数内置函数头头文件文件用途用途double sqrt(double x)double sqrt(double x)
7、math.hmath.hl计算x平方根double pow(double x,double pow(double x,double y)double y)l计算xy次幂double ceil(double x)double ceil(double x)l求大于x最小整数,并以double形式显示double floor(double x)double floor(double x)l求小于x最大整数,并以double形式显示int toupper(int x)int toupper(int x)ctype.hctype.hl假如x为小写字母,则返回对应大写字母int tolower(int x
8、)int tolower(int x)l假如x为大写字母,则返回对应小写字母int rand(void)int rand(void)stdlib.stdlib.h h产生一个随机数void exit(int retval)void exit(int retval)终止程序惯用库函数惯用库函数使用库函数普通方法:使用库函数普通方法:1 1、函数功效、函数功效2 2、函数参数数目和次序,及各参数意义和类型、函数参数数目和次序,及各参数意义和类型3 3、函数返回值意义和类型、函数返回值意义和类型4 4、需要使用包含文件、需要使用包含文件第9页 函数定义格式函数定义格式函数体函数体正当标识符正当标识符
9、函数返回值类型函数返回值类型函数类型函数类型 函数名(形参类型说明表)函数名(形参类型说明表)说明部分说明部分语句部分语句部分return 语句语句以下以下红色红色为函数为函数6 6个元素个元素函数头部函数头部第10页v参数参数:普通用于一个函数把数据传递给另一个函数(调用:普通用于一个函数把数据传递给另一个函数(调用者和被调用者之间),实现函数之间通信。定义函数时候者和被调用者之间),实现函数之间通信。定义函数时候,函数参数是,函数参数是形式参数形式参数,是对一件详细事件可能需要数据,是对一件详细事件可能需要数据假设。假设。v返回值返回值:即函数带回来值。而即函数带回来值。而返回值类型返回值
10、类型是在定义函数时指是在定义函数时指定,即用定,即用“返回值类型返回值类型”指定函数类型。指定函数类型。v1 1、假如类型标识符为、假如类型标识符为voidvoid则表示不需要带回函数值;则表示不需要带回函数值;v2 2、假如没有类型标识,则、假如没有类型标识,则TC2.0TC2.0默认返回值类型是默认返回值类型是intint(在(在vc+6.0vc+6.0中则认为默认为中则认为默认为voidvoid,视编译器不一样而,视编译器不一样而不一样)。不一样)。v函数体函数体:一对花括号里面内容:一对花括号里面内容(包含申明部分和语句部包含申明部分和语句部分分)又被称为函数体,当函数体为空时候,该函
11、数也被又被称为函数体,当函数体为空时候,该函数也被叫做叫做空函数空函数,就是说它什么也不做。,就是说它什么也不做。第11页例例6-1 计算两个整数平均数函数。计算两个整数平均数函数。/*函数功效:就算平均数函数功效:就算平均数函数入口参数:整型函数入口参数:整型x,存放第一个运算数,存放第一个运算数 整型整型y,存放第二个运算数,存放第二个运算数函数返回值:平均数函数返回值:平均数*/int Average(int x,int y)int result;result=(x+y)/2;return result;第12页 大多数情况下,调用者大多数情况下,调用者(主调函数主调函数)和被调用者和被
12、调用者(被被调用函数调用函数)之间有数据传递关系,也就是说该函数之间有数据传递关系,也就是说该函数有参数(能够称为有参数(能够称为有参函数有参函数,不然叫做,不然叫做无参函数无参函数)。在定义函数时函数名后面括号中参数称为在定义函数时函数名后面括号中参数称为“形式形式参数参数”(简称(简称“形参形参”),在主调函数中调用一),在主调函数中调用一个函数时,函数名后面括号中参数(能够是一个个函数时,函数名后面括号中参数(能够是一个“表示式表示式”)称为)称为“实际参数实际参数”(简称(简称“实参实参”)。)。参数和参数传递方式参数和参数传递方式6.2.3 6.2.3 函数参数和返回值函数参数和返回
13、值第13页例例6-2调用函数时数据(参数)传递。调用函数时数据(参数)传递。#include void main()int max(int x,int y);int a,b,c;scanf(%d,%d,&a,&b);c=max(a,b);printf(max is%d,c);int max(int x,int y)/*定义有参函数定义有参函数max*/int z;z=xy?x:y;return(z);运行情况以下:运行情况以下:7,8Max is 8第14页关于形参和实参说明:关于形参和实参说明:a)a)在定义函数中指定在定义函数中指定形参,在函数还未被调用时,它形参,在函数还未被调用时,它们
14、并不占用内存中存放单元们并不占用内存中存放单元。只有在发生函数调用。只有在发生函数调用时,函数时,函数maxmax中形参才被分配内存单元。在调用结束中形参才被分配内存单元。在调用结束后,形参所占内存单元也被释放。后,形参所占内存单元也被释放。b)b)实参能够是常量、变量或表示式,比如:实参能够是常量、变量或表示式,比如:max(3,a+b);max(3,a+b);但要求它们有确定值。在调用时将实参值赋给形参。但要求它们有确定值。在调用时将实参值赋给形参。参数和参数传递方式参数和参数传递方式第15页关于形参和实参说明:关于形参和实参说明:c)c)在被定义函数中,必须指定形参类型。在被定义函数中,
15、必须指定形参类型。d)d)实参加形参类型应相同或赋值兼容。实参加形参类型应相同或赋值兼容。e)e)在在C C语言中,语言中,实参向形参数据传递是实参向形参数据传递是“值传递值传递”,单向传递单向传递,只由实参传给形参,而不能由形参传回,只由实参传给形参,而不能由形参传回来给实参。来给实参。f)f)在内存中,实参单元与形参单元是不一样单元。在内存中,实参单元与形参单元是不一样单元。参数和参数传递方式参数和参数传递方式第16页2222abxy图6-3 参数值传递221015abxy图6-4 实参值不变参数和参数传递方式参数和参数传递方式第17页int Check(int num)if(num%5=
16、0)return 1;else return 0;l通常,希望经过函数调用使主调函数能得到一个确定值,这通常,希望经过函数调用使主调函数能得到一个确定值,这就是函数返回值,也称函数值。就是函数返回值,也称函数值。lC C 语言中语言中 returnreturn 语句用于向调用函数返回值,语句用于向调用函数返回值,语法以下语法以下:returnreturn(););函数返回值函数返回值第18页void swap(int x,int y)int z;z=x;x=y;y=z;printf(nx=%d,y=%d,x,y);main()int a=10,b=20;swap(a,b);printf(na=
17、%d,b=%dn,a,b);程序输出结果:程序输出结果:x=20,y=10a=10,b=20形式参数(形参)形式参数(形参)实际参数(实参)实际参数(实参)实际参数(实参)实际参数(实参)【例例】编一程序,将主函数中两个变量值传递给编一程序,将主函数中两个变量值传递给swapswap函数中两个形参,交换两个形参值。函数中两个形参,交换两个形参值。单向值传递单向值传递第19页c=max(a,b);(调用调用main函数)函数)(max函数)函数)int max(int x,int y)int z;z=xy?x:y;return(z);图6-2 函数调用函数返回值函数返回值第20页void mai
18、n():ans1=cube(2,5,7);ans2=cube(2,3,4);:int cube(int a,int b,int c)int ans;ans=(a*a*a)+(b*b*b)+(c*c*c);return ans;函数函数主程序主程序ans参数参数(实参实参)参数参数(形参形参)返回值返回值第21页(1)(1)函数返回值是经过函数中函数返回值是经过函数中returnreturn语句取得。语句取得。说明说明returnreturn语句将被调用函数中一个确定值语句将被调用函数中一个确定值带回主调函数中去。带回主调函数中去。v 假如需要从被调用函数带回一个数假如需要从被调用函数带回一个数
19、值,则被调用函数中必须包含值,则被调用函数中必须包含reutrn reutrn 语语句。句。v假如不需要则能够不要假如不需要则能够不要returnreturn语句。语句。v一个函数中能够有一个以上一个函数中能够有一个以上returnreturn语语句,执行到哪一个句,执行到哪一个 returnreturn语句,则哪个语句,则哪个语句起作用。语句起作用。vreturnreturn语句后面括号也能够不要,如语句后面括号也能够不要,如“return z;”return z;”和和“return(z);”return(z);”等价。等价。vreturnreturn后面值能够是一个表示式。比如,后面值能
20、够是一个表示式。比如,例例6.26.2中函数中函数maxmax能够改写以下:能够改写以下:max(int x,int y)max(int x,int y)return(xy?x:y);return(xy?x:y);第22页(2)函数类型。既然函数有返回值,这个值当然应属于某一个确定类型,应该在定义函数时指定函数值类型。比如下面是3个函数首行:int max(float x,float y)/*函数值为整型*/char letter(char c1,char c2)/*函数值为字符型*/double min(int x,int y)/*函数值为双精度型*/在C语言中,凡不加类型说明函数,自动按整
21、型处理。第23页(3)(3)在定义函数时指定函数类型普通应该和在定义函数时指定函数类型普通应该和returnreturn语句语句中表示式类型一致。中表示式类型一致。例例6.26.2中指定中指定maxmax函数值为整型,而变量函数值为整型,而变量z z也被指定为整型,也被指定为整型,经过经过returnreturn语句把语句把z z值作为值作为maxmax函数值,由函数值,由maxmax带回主调函数。带回主调函数。z z类型与类型与maxmax函数类型是一致,是正确。函数类型是一致,是正确。v假如函数值类型和假如函数值类型和returnreturn语句中表示式值语句中表示式值不一致,则以函数类型
22、为准。对数值型数不一致,则以函数类型为准。对数值型数据,能够自动进行类型转换。即函数类型据,能够自动进行类型转换。即函数类型决定返回值类型。决定返回值类型。(4)(4)对于不带返回值函数,应该用对于不带返回值函数,应该用“void”void”定义函数为定义函数为“无类型无类型”(或称(或称“空类型空类型”)。)。这么,系统就确保不使函数带回任何值,即禁止在调用函这么,系统就确保不使函数带回任何值,即禁止在调用函数中使用被调用函数返回值。此时在函数体中不得出现数中使用被调用函数返回值。此时在函数体中不得出现returnreturn语句。语句。第24页例例6-3 6-3 返回值类型与函数类型不一样
23、。返回值类型与函数类型不一样。#include void main()int max(int x,int y);float a,b int c;scanf(%f,%f,&a,&b);c=max(a,b);printf(max is%d,c);int max(float x,float y)float z;/*z为实型变量为实型变量*/z=xy?x:y;return(z);运行情况以下:1.5,2.5Max is 2第25页6.3.1 6.3.1 函数调用普通形式函数调用普通形式 函数调用普通形式为函数调用普通形式为 函数名函数名(实参表列实参表列););注意事项:注意事项:(1)假如是调用无参
24、函数,则假如是调用无参函数,则“实参表列实参表列”能够没有,能够没有,不过括号不能省略。不过括号不能省略。(2)假如实参表列包含多个实参,则各个参数间用逗假如实参表列包含多个实参,则各个参数间用逗号隔开。号隔开。实实参参能能够够是是常常量量、变变量、表示式、函数等量、表示式、函数等 6.3 6.3 函数调用函数调用 第26页注意事项:注意事项:(3)(3)赋值对应关系:赋值对应关系:实参实参1-1-形参形参1 1 实参实参2-2-形参形参2 2 实参实参n-n-形参形参n n (4)(4)实参表求值次序(即实参赋值给形参次序)实参表求值次序(即实参赋值给形参次序)因系统而定。因系统而定。TCT
25、C、BCBC、VCVC均是自右向左均是自右向左,也就是说最,也就是说最右边实参最先赋值给最右边形参右边实参最先赋值给最右边形参,最左边实参最终赋值给最左边实参最终赋值给最左边形参。但最左边形参。但VCVC与与TCTC、BCBC在详细赋值时稍有不一样,注在详细赋值时稍有不一样,注意它们之间区分。意它们之间区分。第27页例例6-4 实参求值次序。实参求值次序。#include void main()int f(int a,int b);/*函数申明函数申明*/int i=2,p;p=f(i,+i);/*函数调用函数调用*/printf(%dn,p);int f(int a,int b)/*函数定义
26、函数定义*/int c;if(ab)c=1;else if(a=b)c=0;else c=-1;return(c);问:在问:在Turbo C 2.0Turbo C 2.0和和Turbo C+Turbo C+3.03.0系统上运行结果?系统上运行结果?原型申明原型申明原型申明原型申明 i i为实参为实参 a a、b b为形参为形参 第28页若若按自左至右次序求实参值,则函数调用相当于按自左至右次序求实参值,则函数调用相当于f(2,3)f(2,3),程序运行应得结果为程序运行应得结果为“-1”-1”。若按自右至左次序求实参值,则它相当于若按自右至左次序求实参值,则它相当于f(3,3)f(3,3)
27、,程序运,程序运行结果为行结果为“0”0”。分析:分析:假如本意是按自左而右次序求实参值,即假如本意是按自左而右次序求实参值,即f(2,3)f(2,3)调用,可改写成调用,可改写成:j=i;j=i;k=+i;k=+i;p=f(j,k);p=f(j,k);假如本意是自右而左求实参值假如本意是自右而左求实参值,即即f(3,3)f(3,3)调用,调用,可改写成:可改写成:j=+i;j=+i;p=f(j,j);p=f(j,j);是否有方法让参数确定?是否有方法让参数确定?第29页1.1.函数语句函数语句 把函数调用作为一个语句。这时不要求函数带来返回值,把函数调用作为一个语句。这时不要求函数带来返回值
28、,只要求函数完成一定操作。比如:只要求函数完成一定操作。比如:printstar();printstar();printf(“Hello,World!n”);printf(“Hello,World!n”);2.2.函数表示式函数表示式 函数出现在一个表示式中,这种表示式称为函数表示式。函数出现在一个表示式中,这种表示式称为函数表示式。这是要求函数带回一个确定值以确定参加表示式运算。比如:这是要求函数带回一个确定值以确定参加表示式运算。比如:C=2*max(a,b);C=2*max(a,b);函数函数maxmax是表示式一部分,它值乘是表示式一部分,它值乘2 2再赋给再赋给c c。6.3.2 6
29、.3.2 函数调用方式函数调用方式 按函数在程序中出现位置分,可有按函数在程序中出现位置分,可有3 3种函数调用方式:种函数调用方式:第30页3.3.函数参数函数参数 函数调用作为一个函数实参。比如:函数调用作为一个函数实参。比如:M=max(a,max(b,c);M=max(a,max(b,c);其中其中max(b,c)max(b,c)是一次函数调用,它值作为是一次函数调用,它值作为maxmax另一次调用另一次调用实参。实参。MM值是值是a a、b b、c c三者中最大者。比如:三者中最大者。比如:printf(“%d”,max(a,b);printf(“%d”,max(a,b);也是把也是
30、把max(a,b)max(a,b)作为作为printfprintf函数一个函数。函数一个函数。函数调用作为函数参数,实质上也是函数表示式形式调函数调用作为函数参数,实质上也是函数表示式形式调用一个,因为函数参数原来就要求是表示式形式。用一个,因为函数参数原来就要求是表示式形式。第31页6.3.3 6.3.3 对被调用函数申明和函数原型对被调用函数申明和函数原型#include float count(int,int);void main().float count(int x,int y).l函数原型说明函数原型说明在形式上与函数头部类似,最终加一个分号在形式上与函数头部类似,最终加一个分号。
31、原型说明中参数表里参数名能够不写(只写参数类型)。原型说明中参数表里参数名能够不写(只写参数类型)。第32页问题描述:依据用户选择求不一样形状面积。函数调用示例函数调用示例#includevoid AreaOfRect();void AreaOfTriangle();void AreaOfRound();void main()int select;do printf(0、退出、退出n 1、长方形、长方形n 2、三角形、三角形n 3、圆形、圆形n);printf(请选择功效:请选择功效:);scanf(%d,&select);if(select=0)break;switch(select)cas
32、e 1:AreaOfRect();break;/长方形长方形 case 2:AreaOfTriangle();break;/三角形三角形 case 3:AreaOfRound();break;/圆形圆形 default:printf(输入有误,请在输入有误,请在 04 之间选择。之间选择。n);while(1);void AreaOfRect()int x,y;printf(请输入长方形长请输入长方形长:);scanf(%d,&x);printf(请输入长方形宽请输入长方形宽:);scanf(%d,&y);printf(面积为:面积为:%dn,(x*y);void AreaOfTriangle
33、()int x,y;printf(请输入三角形底请输入三角形底:);scanf(%d,&x);printf(请输入三角形高请输入三角形高:);scanf(%d,&y);printf(面积为:面积为:%dn,(x*y)/2);void AreaOfRound()int r;printf(请输入圆形半径请输入圆形半径:);scanf(%d,&r);printf(面积为:面积为:%dn,3.14*r*r);函数原型第33页 在在一一个个函函数数中中调调用用另另一一个个函函数数(即即被被调调用用函函数数)需需要要具具备备条件以下条件以下:1.1.首先首先被调用函数必须是已经存在函数被调用函数必须是已经
34、存在函数(库函数或自定义函(库函数或自定义函数)。数)。2.2.假如使用库函数假如使用库函数,还应该在文本开头用,还应该在文本开头用#include#include命令将调用命令将调用相关库函数时所需用到信息(这些信息是一些常量和函数相关库函数时所需用到信息(这些信息是一些常量和函数原型)原型)“包含包含”到本文件中来,不然函数将不能正常地得到本文件中来,不然函数将不能正常地得到调用。比如,前面经惯用到过:到调用。比如,前面经惯用到过:#include#include 3.3.3.3.假如使用用户自定义函数假如使用用户自定义函数,则假如该函数被定义位置在,则假如该函数被定义位置在调用它函数(即
35、主调函数)后面(在同一文件中),应该调用它函数(即主调函数)后面(在同一文件中),应该在主调函数中对被调函数作申明。假如被调用函数定义出在主调函数中对被调函数作申明。假如被调用函数定义出现在主调函数之前,能够无须加以申明。现在主调函数之前,能够无须加以申明。第34页对于函数位置:对于非int函数,调用单位位置要在被调用单位在下面,不然编译产生错误。处理方法是:在调用单位加上被调用函数声(说)明。void f()main()f();void f()main()f();void f()main()void f();f();第35页 例例6-5 编编制制子子函函数数实实现现求求两两个个单单精精度度实
36、实数数和和,main函函数数调调用该函数时候要先申明。用该函数时候要先申明。/*6_5.c*/#include void main()float add(float x,float y);/*对被调用函数add申明*/float a,b,c;scanf(%f,%f,&a,&b);c=add(a,b);printf(sum is%fn,c);float add(float x,float y)/*函数首部*/float z;/*函数体*/z=x+y;return(z);运行情况以下:3.6,6.5sum is 10.100000float add(float,float);第36页总而言之,总而
37、言之,函数原型函数原型普通形式有两种普通形式有两种:(1)(1)函数类型函数类型 函数名(参数类型函数名(参数类型1 1,参数类型,参数类型2 2,参数类型,参数类型n n););(2)(2)函数类型函数类型 函数名(参数类型函数名(参数类型1 1 参数名参数名1 1,参数类,参数类型型2 2 参数名参数名2 2,参数类型参数类型n n 参数名参数名n n););第37页应该注意到函数原型与函数定义是不一样。应该注意到函数原型与函数定义是不一样。l函数定义函数定义是指对函数功效确实立,包含指定函是指对函数功效确实立,包含指定函数名、函数值类型、形参及其类型、函数体等,数名、函数值类型、形参及其
38、类型、函数体等,它是一个完整、独立函数单位。它是一个完整、独立函数单位。l函数申明函数申明作用则是把函数名字、函数类型以及作用则是把函数名字、函数类型以及形参类型、个数和次序通知编译系统,方便在形参类型、个数和次序通知编译系统,方便在调用该函数时系统按此进行对照检验(比如,调用该函数时系统按此进行对照检验(比如,函数名是否正确,实参加形参类型和个数是否函数名是否正确,实参加形参类型和个数是否一致等)。一致等)。第38页6.3.4 6.3.4 嵌套调用嵌套调用 在在C C语语言言中中,函函数数定定义义是是平平行行,不不允允许许进进行行函函数数嵌嵌套套定定义义,即即在在一一个个函函数数体体中中不不
39、允允许许定定义义另另一一个个函函数数。而而函函数数之之间间调调用用能能够够是是任任意意,即即允允许许在在一一个个函函数数体体内内再再调调用用其其它它函函数数,在在函函数数体体中中再再调调用用其其它它函函数数称称为为函函数数嵌嵌套套调调用用。第39页void reverse():#includevoid main():palindrome();:void palindrome():reverse();:从一个函数调用另一个函数称为从一个函数调用另一个函数称为函数嵌套调用函数嵌套调用 比如:比如:C C要求:函数定义不可嵌套,但能要求:函数定义不可嵌套,但能够嵌套调用函数够嵌套调用函数第40页例例
40、6-6函数嵌套调用。函数嵌套调用。main()aia();aia()ber();ber()cal();cal().图图6-5 函数嵌套调用函数嵌套调用89246135710 函数函数main调用了调用了aia,aia调用了调用了ber,ber又调又调用了用了cal。其调用过程和返回过程如图所表示。其调用过程和返回过程如图所表示。void aia(),ber(),cal();main()printf(Im in main.n);aia();void aia()printf(Now Im in aia.n);ber();void ber()printf(Now Im in ber.n);cal()
41、;void cal()printf(Now Im in cal.);第41页 一一个个函函数数直直接接或或间间接接地地调调用用函函数数本本身身,这这种种调调用用称称为为递递归归调调用用,前前者者称称为为直直接接递递归归,后后者者称称为为间接递归间接递归。递归调用函数称为。递归调用函数称为递归函数递归函数。因因为为递递归归非非常常符符合合人人们们思思维维习习惯惯,而而且且许许多多数数学学函函数数及及许许多多算算法法或或数数据据结结构构都都是是递递归归定定义义,所所以,递归调用颇具实用价值。以,递归调用颇具实用价值。6.3.4 6.3.4 函数递归调用函数递归调用 第42页/*此函数用于计算 n
42、阶乘*/int factorial(int n)int a;if(n=1)return 1;else a=n*factorial(n-1);return a;在一个函数体内调用本身称为函数在一个函数体内调用本身称为函数递归调用递归调用 第43页例6-7利用函数递归调用来求n阶乘。#include long fact();/*申明被调用函数返回值为长整型申明被调用函数返回值为长整型*/main()/*主函数主函数*/int h,i;printf(请输入任一正整数请输入任一正整数:n);scanf(%d,&h);for(i=0;i=h;+i)printf(%d!=%ldn,i,fact(i);lo
43、ng fact(int n)/*求阶乘函数求阶乘函数*/long int res;if(n=0)res=1;else res=n*fact(n-1);/*递归调用递归调用*/return(res);请输入任一正整数请输入任一正整数:6 0!等于等于11!等于等于12!等于等于23!等于等于64!等于等于245!等于等于1206!等于等于720程序执行后显示程序执行后显示:第44页6.3.6 程序设计举例(使用函数编写程序)例例6-86-8 输出输出5 5之内数字金字塔。之内数字金字塔。例例6-9 6-9 输入精度输入精度e e,使用格里高利公式求,使用格里高利公式求 近近似值,准确到最终一项绝
44、对值小于似值,准确到最终一项绝对值小于e e。要求。要求定义和调用函数定义和调用函数funpi(e)funpi(e)求求 近似值。近似值。例例6-10 6-10 采取递归方式实现二分查找。二分查采取递归方式实现二分查找。二分查找算法是对有序数列进行查找操作一个有效找算法是对有序数列进行查找操作一个有效操作。实际上,这种查找方法是一个递归过操作。实际上,这种查找方法是一个递归过程。程。第45页结构体变量作为函数参数结构体变量作为函数参数 140140页页例例5-3 5-3 将键盘输入相关学生档案信息用函数list实现。#include struct STUD char name20;long n
45、um;int age;char sex;float score;void list(struct STUD stud)printf(%-20s%-10ld%-4d%-4c%-6.2fn,stud.name,stud.num,stud.age,stud.sex,stud.score);void main()struct STUD stud3;int i;for(i=0;i3;i+)printf(Input all information about the No.%d student:n,i+1);getchar();gets(studi.name);scanf(%ld,%d,%c,%f,&st
46、udi.num,&studi.age,&studi.sex,&studi.score);printf(n%-20s%-10s%-4s%-4s%-6sn,Name,Num,Age,Sex,Scores);for(i=0;i y?x:y;z=x y?x:y;return(z);return(z);void f2()void f2()printf(%dn,printf(%dn,z z););局部变量局部变量局部变量局部变量 变量变量变量变量x x x x、y y y y、z z z z作用域作用域作用域作用域引用错误!引用错误!引用错误!引用错误!第53页 说明说明说明说明 (1)(1)主函数主函数
47、main()main()中定义变量也是局部变量中定义变量也是局部变量,它只能在,它只能在主函数中使用,其它函数不能使用。同时,主函数中也不能主函数中使用,其它函数不能使用。同时,主函数中也不能使用其它函数中定义局部变量。使用其它函数中定义局部变量。int f3(int x);int f3(int x);void main()void main()int int a a=2,=2,b b;b=a+y;b=a+y;printf(%dn,b);printf(%dn,b);int f3(int int f3(int x x )int int y y;y=a+5;y=a+5;return(y);retu
48、rn(y);局部变量局部变量局部变量局部变量 变量变量变量变量a a a a、b b b b作用域作用域作用域作用域变量变量变量变量x x x x、y y y y作用域作用域作用域作用域局部变量局部变量局部变量局部变量 错误!错误!错误!错误!错误!错误!错误!错误!第54页 说明说明说明说明 (2)(2)形参变量属于被调用函数局部变量;形参变量属于被调用函数局部变量;实参变量则属实参变量则属于全局变量或调用函数局部变量。于全局变量或调用函数局部变量。(3)(3)允许在不一样函数中使用相同变量名允许在不一样函数中使用相同变量名,它们代表不,它们代表不一样对象,分配不一样单元,互不干扰,也不会发
49、生混同。一样对象,分配不一样单元,互不干扰,也不会发生混同。#include#include void subf();void subf();void main()void main()int a,b;int a,b;a=3,b=4;a=3,b=4;printf(main:a=%d,b=%dn,a,b);printf(main:a=%d,b=%dn,a,b);subf();subf();printf(main:a=%d,b=%dn,a,b);printf(main:a=%d,b=%dn,a,b);void subf()void subf()int a,b;int a,b;a=6,b=7;a=6
50、,b=7;printf(subf:a=%d,printf(subf:a=%d,b=%dn,a,b);b=%dn,a,b);运行结果:运行结果:运行结果:运行结果:main:a=3,b=4main:a=3,b=4subf:a=6,b=7subf:a=6,b=7main:a=3,b=4main:a=3,b=4变量名相同变量名相同变量名相同变量名相同 第55页 说明说明说明说明 (4)(4)在复合语句中定义变量也是局部变量在复合语句中定义变量也是局部变量,其作用域只在,其作用域只在复合语句范围内。其生存期是从复合语句被执行时刻到复合语复合语句范围内。其生存期是从复合语句被执行时刻到复合语句执行完成时