《谭浩强版经典课件C语言程序入门函数》由会员分享,可在线阅读,更多相关《谭浩强版经典课件C语言程序入门函数(59页珍藏版)》请在金锄头文库上搜索。
1、第五章 函数2000级统招主 讲:樊广军第五章 函数第五章第五章 函数函数本章目标本章目标1. 进一步理解多个函数构成一个C程序2. 进一步了解和熟悉库函数3. 学会编写自已的函数4. 理解函数的调用关系5. 理解函数中参数的传递机制第五章 函数一、一、C程序模块程序模块一个一个C程序可由一个程序可由一个main( )函数和多个函数和多个其它函数构成。其它函数构成。5 5. .1 1 C C程程序序模模块块第五章 函数 其它函数指的是:其它函数指的是: 系统函数系统函数由系统提供,放在头文件中由系统提供,放在头文件中自编函数自编函数由程序设计人员编写由程序设计人员编写第五章 函数二、函数的调用
2、二、函数的调用如:如:mainfunafunbfuncfundfunxfuny第五章 函数 所有的函数都所有的函数都 具有两种特征:具有两种特征: 返回值返回值参数参数(返回值和参数都是可缺省的返回值和参数都是可缺省的)第五章 函数5 5. .2 2 库库函函数数一、库函数简介一、库函数简介系统自带的标准库函数根据不同的功能作用放在不同的头文件中。第五章 函数如:stdio.h用于标准输入/输出math.h用于数学计算ctype.h用于字符处理string.h用于字串处理time.h用于时间/日期的处理dir.h用于控制目录和路径graphics.h用于图形操作dos.hbios.h用于接口处
3、理第五章 函数二、库函数的作用二、库函数的作用 使程序更具有“ 独立性”和“ 可移植”性。 使用时只需在程序的开头加上一条语句:#include 根据使用的函数来确定 使程序具有“ 模块化”。第五章 函数例例1 1:求两个浮点型数值x/y的余数。 (注意:不能写成3.6%1.7)#include #include main( ) float x, y, z;scanf(%f%f, &x, &y);z=fmod(x, y);printf( z=%f, z);第五章 函数例例2 2:P119随机数程序:程序:P120程序程序: P122第五章 函数5.3 5.3 自定义函数自定义函数一、自定义函数
4、的作用一、自定义函数的作用 使程序具有使程序具有“ 积木积木”功能。功能。(模块化模块化) 使程序具有使程序具有“ 重构重构”功能。功能。第五章 函数二、二、 函数的定义及调用函数的定义及调用 定义定义存储类型符存储类型符 返回值类型符返回值类型符 函数名函数名(形参表形参表列列)形参说明形参说明 说明部分说明部分语句语句第五章 函数 调用调用 变量名=函数名(实参表列);(变量名的类型必须与函数的返回值类型相同) 函数名(实参表列);第五章 函数三、函数声明三、函数声明一般情况下,函数被调用之前必须要有函数声明函数声明。(函数声明的意义在于提供函数原型)函数声明的格式:返回值类型符返回值类型
5、符 函数名函数名(形参类型形参类型);第五章 函数例例1:1: 求二个数中的最大值 int max (x, y) int x, y; int z; z=xy? x:y; return (z); 用用return语句,返回函数的值。语句,返回函数的值。或:int max (int x, int y) int z; z=xy? x:y; return (z); 四、举例四、举例第五章 函数通过函数调用求二个数中的最大值:通过函数调用求二个数中的最大值: #include int max (int, int); /*函数原型函数原型*/main( ) int a, b, t;scanf(%d%d,
6、&a, &b);t=max(a, b); /*函数调用函数调用*/printf(value of maximize is: t=%d,t);int max(int x, int y) /*函数定义函数定义*/ int z;z=xy? x:y;return(z);第五章 函数#include float add( ); /*函数说明函数说明*/main ( ) float a, b, c; scanf(%f, %f,&a, &b); c=add(a, b); /*函数调用函数调用*/ printf (sum= %f;c); float add( float x, float y); /*函数定义
7、函数定义*/ float z; z=x+y; return z;例例2:2: 求二实数之和求二实数之和若函数的定义放在若函数的定义放在main( )函数之前可省略函函数之前可省略函数说明。数说明。第五章 函数第五章 函数 #include float add( float x, float y); /*函数定义函数定义*/ float z; z=x+y; return z; main ( ) float a, b, c; scanf(“ %f, %f”,&a, &b); c=add(a, b); /*函数调用函数调用*/ printf (sum= %f;c); 例例3:3: 求二实数之和(将例
8、1程序改写如下:)例例4.4. P113第五章 函数第五章 函数1. 形参与实参形参与实参调用时调用时: 实参值单向传递形参。 函数被调用时,临时分配单元给形参,调用完毕, 这些单元被释放。实参实参: 出现在调用函数中, 形参: 出现被调用函数中。五、自定义函数中的几个重要特征五、自定义函数中的几个重要特征第五章 函数 实参可为表达式,只传递表达式的值。 实参、形参类型一致。 可在形参表列中对形参说明。注注: :! ?第五章 函数2. 函数返回函数返回或 return 变量的值; 通过return语句将流程返回主调函数。 return; 函数无返回值 return 表达式的值;第五章 函数3.
9、 函数名函数名要选择一个简洁的有意义的名字作为要选择一个简洁的有意义的名字作为函数名。函数名。从函数名可以反映出函数的功能。从函数名可以反映出函数的功能。第五章 函数六、传值调用和传引用六、传值调用和传引用( (传址传址) )调用调用1. 传值调用传值调用方式:方式:函数的实参和形参的类型均为简单变量。当实参传递形参时系统会建立一份实参的拷贝给形参。当函数调用完毕,这份实参的拷贝消失。特点:特点:传值调用不会影响实参的值。第五章 函数2. 传引用传引用(传址传址)调用调用把实参形参后传递形参变量和实参变量共同内存地址。特点:特点:形参变量的值的变化会影响实参的值的改变。第五章 函数5.4 5.
10、4 函数的存储类型函数的存储类型一、标识符的属性一、标识符的属性一、标识符的属性一、标识符的属性一个标识符的属性除了前面已讲过的基本属性外,还具有一些其它的属性: 存储类别存储类别 存储期存储期第五章 函数二、存储类别二、存储类别1. 存储类型和存储期存储类型和存储期 自动型自动型 (auto) 寄存器型寄存器型(register) 外部型外部型(extern) 静态型静态型(static)自动存储期自动存储期静态存储期静态存储期第五章 函数2. 存储期的性质存储期的性质 自动存储:只有变量才具有自动存储期自动存储:只有变量才具有自动存储期如函数中的变量说明:auto float x, y;a
11、uto int m, n;作作用用:进入到函数块中,该变量存在,退出函数块后该变量消失。程序中大部分变量都具有自动存储期。第五章 函数 静态存储:可用于变量和函数静态存储:可用于变量和函数如:如:static in t;作用:作用:从程序开始执行起就一直存在,始终占据内存单元,直到程序结束运行。第五章 函数 对静态存储变量,若定义时赋初值,则程序运行中仅在第一次调用时赋初值,下一次调用不再赋初值,而是使用上一次调用的值。特别提醒:特别提醒: 对静态存储变量,若定义时不赋初值,则系统置初值0,而动态变量不赋初值则值不确定。第五章 函数#include int fac (n) /*函数定义函数定义
12、*/ int n; static int f=1; f=fn; return(f); main ( ) int i; for (i=1; i=5; i+) printf (%d!=%dn, i, fac(i); 例:例:求求n!第五章 函数第五章 函数 1!1 2!2 3!6 4!24 5!120 每一次调用fac(i),打印一个i!,同时保留这个i!的值以便下次再乘(i+1)。运行结果为:运行结果为:第五章 函数5.5 5.5 标识符的作用域标识符的作用域 标识符可以具有四种作用域。标识符可以具有四种作用域。 函数作用域 文件作用域 块作用域 函数原型作用域(作用域: 有效范围) 可根据标识
13、符的作用域区分局部变量和可根据标识符的作用域区分局部变量和全局变量。全局变量。第五章 函数一、局部变量一、局部变量一、局部变量一、局部变量 凡在函数(含main 函数)内部定义的变量称为局部变量。局部性局部性: 局部变量仅在函数内部有效。第五章 函数2. 形参为局部变量。形参为局部变量。 3. 在在复复合合语语句句中中可可定定义义仅仅在在复复合合语语句句中中有有效的临时变量。效的临时变量。1. 不不同同的的函函数数可可有有同同名名同同类类型型的的变变量量,它它们占不同的内存单元们占不同的内存单元, 互不影响。互不影响。第五章 函数二、全局变量二、全局变量 一个源文件中, 在所有函数之外定义的变
14、量为全局变量。有效性有效性有效性有效性: : : : 自定义位置开始至文件结尾全部有效。第五章 函数例例: : int p=1, q=5; float f1(a) int a; int b, c; char c1, c2; p,q的作用范围的作用范围c1, c2的作用范围的作用范围 char f2(x,y); int x, y; int i, j; main ( ) 第五章 函数第五章 函数1. 全局变量所作用到的函数,相当于这些函全局变量所作用到的函数,相当于这些函数的公共变量。当一个函数对其值进行改数的公共变量。当一个函数对其值进行改变后变后,另一个函数使用该变量的值亦相应改另一个函数使用
15、该变量的值亦相应改变。变。好处好处: : 函数之间值传递。函数之间值传递。2. 不要随意使用全局变量。一是始终占据内不要随意使用全局变量。一是始终占据内存单元;二是由于函数依赖于外部定义的存单元;二是由于函数依赖于外部定义的变量,减少了通用性。变量,减少了通用性。注意注意第五章 函数3. 不在作用域内函数。若使用全局(外部)变量,需在函数体内加上extern保留字。4. 全局和局部变量同名时,局部变量有效。第五章 函数 float f1 (x) int x; extern int a, b; int a0; b= 1 main ( ) a, b作用域例例: :第五章 函数例例1 1:/*-ex
16、p81.c-*/#include int fun1(int x, int y); int a, b, z; main( ) int u, m=0; a=24; b=42; printf(1)-a=%d, b=%d, m=%dn, a, b, m);m=m+10; u=fun1(a, b); printf(2)-a=%d, b=%d, u=%d, m=%dn, a, b, u, m);m=m+10; a=z a; b=z b; u=fun1(a, b); printf(3)-a=%d, b=%d, u=%d, m=%dn, a, b, u, m); 第五章 函数第五章 函数 int fun1(i
17、nt x, int y) int m; m=x+y; printf(chang a&b:-a=%d, b=%d, z=%d, m=%dn, a, b, z, m);a=a+10; b=b+20; z=x+y; return (z);第五章 函数第五章 函数(1) -a=24, b=42, m=0运行结果:运行结果:chang a&b:-a=34, b=62, z=66, m=66(2) -a=34, b=62, u=66, m=10chang a&b:-a=42, b=24, u=36, m=36(3) -a=42, b=24, u=36, m=20例例2: 2: P128第五章 函数5.65
18、.6 递归调用递归调用一、递归的特点一、递归的特点一个问题能够成为递归必须具备的条件是:一个问题能够成为递归必须具备的条件是: 后一部分与原始问题类似后一部分与原始问题类似 后一部分是原始问题的简化后一部分是原始问题的简化第五章 函数1. 直接递归调用:直接递归调用:函数直接调用本身函数直接调用本身二、程序中的递归方式二、程序中的递归方式2. 间接递归调用:间接递归调用:函数间接调用本身函数间接调用本身第五章 函数直接调用: int f(x) int x; int y, z; z=f (z); 间接调用: int f1 (x) int x; int y, z; z=f2 (y); int f2
19、 (t) int t; int a, b; a=f1 (b); 以下表示了递归的概念以下表示了递归的概念.第五章 函数显然显然: : 上述例子会无限递归 (无限执行)。所以, 在递归调用时都必须有条件限制。n!=1 (n=0, 1)n(n1)! (n1)当条件成立, 调用递归, 否则结束。例例1:1: 求n!1. 从数学上定义从数学上定义第五章 函数 #include long fac(int n) /*函数定义函数定义, 计算计算n!*/ long f; if (n0) printf(input error!n); else if (n= = 0 n= =1)f =1; else f =nf
20、ac(n 1); return (f); 2. 2. 程序程序程序程序: :第五章 函数第五章 函数 main ( ) int n; long y; printf(input a integer! ) scanf (%d, &n); y=fac(n); /*函数调用函数调用, 计算计算n!*/ printf(%d!=%15ld, n, y);第五章 函数第五章 函数3. 执行过程执行过程:设设: : 输入 5 (n=5)第1次调用:y=fac(5) 返回:y=5fac(4)第2次调用:y=5*4fac(3)第3次调用:y=5*4*3fac(2)第4次调用:y=5*4*3*2fac(1)第5次调
21、用:y=5*4*3*2*1*fac(0)第五章 函数例例2:2: 汉诺塔(Hanoi)问题BC问题问题: : 将A塔上n个盘子移至C(借助于B)。 移动时,保证三个塔始终是大盘在下,小盘在上。An个盘子第五章 函数必须用递归方式解决必须用递归方式解决1) 先将A塔n 1个盘子借助于C移至B上2) 将A上剩下的一个移至C上.3) 将B上n 1个盘子借助于A移至C上.可以看到可以看到: 1)、3)为同一问题,都为n 1个盘子借助于一个 空塔移至另一塔上。第五章 函数#include void move (char getone,char putone) /*函数定义函数定义*/ printf(“
22、%c %cn ”, getone, putone);void hanoi (int n, char one, char two, char three) /*将将n个盘从个盘从one借助借助two,移到移到three*/ if (n= =1) move (one, three); else hanoi (n1, one, three, two); move (one, three); /*函数调用函数调用*/ hanoi (n1, two, one, three); 程序如下:程序如下:第五章 函数第五章 函数 main ( ) int m; printf ( input the number
23、 of diskes :); scanf( %d ,&m); printf( The step to moving %3d diskes:n , m); hanoi (m, A, B, C); /*函数调用函数调用*/第五章 函数第五章 函数 input the number of diskes:3 The step to moving 3 diskes: A C A B C B A C B A B C A C运行情况如下:运行情况如下:第五章 函数 move (getone, putone) 表示从getone 塔移一个盘子至putone塔 hanoi(n, one, two, three)
24、 表示n个盘子从one塔借助于two塔(空)移至three塔,调用时塔用字符常量A , B , C 表示。在程序中有两个函数在程序中有两个函数: :第五章 函数例例3 3: P.132Fibonacci 数列第五章 函数本本 章章 小小 结结1. 库函数的定义和使用方法。2. 函数的定义和使用方法。3. 变量的存储类别和作用域。4. 递归函数的概念和使用。本章主要介绍的内容:本章主要介绍的内容:第五章 函数1. P143 自我测验练习5.15.72. P143 5.8 5.11 5.14 5.165.16 5.22 5.23 5.315.33 5.373.自我练习:自我练习: 5.12 5.13 5.30 5.465.49