C语言课件:第八章函数.ppt_第1页
C语言课件:第八章函数.ppt_第2页
C语言课件:第八章函数.ppt_第3页
C语言课件:第八章函数.ppt_第4页
C语言课件:第八章函数.ppt_第5页
已阅读5页,还剩33页未读 继续免费阅读

下载本文档

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

文档简介

1,第 8 章 函数,2,在进行程序设计时,程序员总是将复杂的问题进行 分解, 化整为零。编写一段小程序就能解决一个小问题, 然后将这些小程序拼装起来就能解决非常大而复杂的问 题。在 C 中,这些小程序统称为函数。,在 C 中,由系统提供的函数放在函数库中供用户选 用,以减少重复编写程序模块的工作量。, 所有函数都是平行的,相互独立不能嵌套,但可以相 互调用。, C 函数分标准函数(库函数)和自定义函数。, C 函数本身分有参函数和无参函数。,8.1 概述,第 8 章 函数,3,8.2 函数定义的一般形式,1无参函数的定义形式,类型标识符 函数名( ) 说明部分 ; 语句; ,无参函数一般不需要返回函数值,可以省略类型标识符。,2有参函数的定义形式,类型标识符 函数名(形式参数表) 形式参数说明; 说明部分 ; 语句; ,4,例: int max(x,y) int x, y; / 形式参数说明 / int z; / 函数体中的说明部分 / z=xy ? x : y; return(z); ,类型说明符 函数名( ) ,“空函数”什么操作也不做。其作用是在此处留一函数的 位置,以便将来扩充功能之用。函数名也在将来换取实 际的函数名。,3“ 空函数 ”,5,8.3 函数参数和函数的值,1形式参数和实际参数,例8.2 从键盘输入两个数,输出其中较大的一个。 main( ) int a, b, c ; scanf(“%d,%d”, ,6,注意:, 形参变量在被调用前不占用存储单元;在被调用结束 后,形参所占存储单元亦被释放。, 实参可以是常量、变量或表达式。, 必须指定形参类型,且必须与实参的类型一致。, 实参对形参的数据传递是“值传递”。即单向传递,不 能逆传。, 可以在形参表中直接说明形参类型。,如:,int max(int x, int y);,float fun(int a10, int n);,7,2函数的返回值, 函数的返回值是通过return语句获得的。当不需返 回函数值时,可省去return语句。, return语句的后面可以有括号,也可以没有。,如:,return z ; return(z);, return语句的后面可以是变量,也可以是表达式。,如:,return(x y ? x : y);, return语句返回值的类型应与该函数的类型一致。 否则以函数类型为准。,8, 若函数中没有return语句,则该函数被调用后也会带 回不确定的值。, int a, b, c ; a = printstar( ); b = print_message( ); c = printstar( ); printf(“%d,%d,%dn”,a,b,c); ,输出的a, b, c的值将是各个被处理的字符串的长度。, 为了明确表示不需要函数返回值,可以用“void”定义 函数为 “无类型”。此时,不得使用 a=printstar( ) 之 类的语句。,凡不需要返回值的函数,一般均定义为“void”类型。,如:,9,8.4 函数的调用,1函数调用的一般形式,函数名(实参表),说明:, 对于无参函数,尽管没有“实参表”,但也不得省略 括号。, “实参表”中的参数之间用逗号分开。, 实参与形参之间的个数及类型必须一一对应。, 对实参求值的顺序是自左至右还是自右至左, 视具体 的系统而定。Turbo C 和 MS C 是按自右至左的顺 序求值。,10,例8.4 main( ) int i =2 , p ; p = f ( i , + + i ); printf ( “%d”, p ) ; int f ( a , b ) ; int a , b ; int c ; if ( a b ) c = 1; else if ( a = = b ) c = 0 ; else c = 1 ; return( c ) ; ,输出结果: 0,b 的值为3,a 的值为3,11,2函数调用的方式,调用函数,可以有如下三种方式:, 将函数调用作为一个语句。,如:,printf(“MS C programming”);,gets(s);, 将被调用的函数写在表达式中。,如:,c = 2 max(a, b);,注意:被调用函数 max 必须有确定的返回值。, 将函数调用作为一个函数的实参。,如:,m = max(max(a, b), c);,3对被调用函数的说明,在一个函数中调用另一个函数时:, 如果被调函数为库函数,则应在文件开头用“#include”命令 声明相应的 “头文件”。,如:,#include “stdio.h” #include “math.h” ,12, 如果被调函数为自定义函数且其定义在主调函数定义之后,则 应在主调函数中说明其类型。,类型标识符 被调函数名( );,如: float add( );,其语句形式为:, 如果被调函数为自定义函数且其定义在主调函数定义之前,则 在主调函数中可不必说明其类型。因为编译程序已知道其类型, 如果被调函数的值是整型或字符型,可不必说明类型,系统自 动按整型说明。, 如果在所有被调函数定义之前、在文件的开头、在函数的外部 已对被调函数作了类型说明,则在各主调函数中可不必说明其 类型。,如:,char letter( ); float f( ); int i( ); main( ) ,/ 主调函数中不必说明它所调用的函数的类型 /,13,例:编程求11999之间的数 m,而 m、m2 和 m3 均是回文数。,如:m=11、m2=121、m3=1331, 。,#include “stdio.h” main( ) long int m; for (m=11; m1000; m+) if ( fun(m) ,14,8.5 函数的嵌套调用,C 语言函数的定义都是相互平行、独立的,不能嵌套定义。但可以嵌套调用函数。所谓函数的嵌套调用就是在被调用的函数中又调用另外的函数。,Main ( ) x=root(x1,x2); /*调用root函数*/ ,Float root (float y1,float y2) y1=f(x) ; /*调用f 函数*/ ,15,8.6 函数的递归调用,自己调用自己,递归一次,分配一次存储 单元,返回时,一层一层返回;,2 递归程序示例,1 递归的概念,递归分为: 直接递归:函数中自己调用自己; 间接递归:在调用其他函数中调用自己。,16,例8.7 有5人排成一队,从最后一人开始,其年龄均比 前面的人大2岁,而最前面的人年龄是10岁, 问 最后一人的年龄是多少岁?,main( ),age(5),age(4)+2,age(n) n=5,age(3)+2,age(n) n=4,age(2)+2,age(n) n=3,age(1)+2,age(n) n=2,age(1),age(n) n=1,age(1)=10,age(2)=12,age(3)=14,age(4)=16,age(5)=18,输出age(5),age(n) int n; int c; if (n=1) c = 10; else c = age(n1) + 2; return(c); ,main( ) printf(“%dn”,age(5); ,运行结果: 18,17,函数的递归调用利用了堆栈技术。在本例中:,Age(5),Age(51)+2,Age(41)+2,Age(31)+2,Age(21)+2,10+2=12,12+2=14,14+2=16,16+2=18,18,Age(21)+2,Age(31)+2,Age(41)+2,Age(51)+2,Age(5),Age(5),Age(51)+2,Age(41)+2,Age(31)+2,Age(21)+2,入栈,出栈,出栈结果,18,例:把一非零的整数倒序打印,main( ) int aa(); int n; scanf(“%d”, ,19,例:读入一串字符,并倒序打印,main( ) char abc(); abc(); char abc() char ch; scanf(“%c”, ,20,例:求两个数的最大公约数,main( ) int gcd (a,b); int n,m; scanf(“%d%d”, ,21,8.7 数组作为函数参数,1数组元素作函数实参,用法与变量参数相同,是单向传递,即“值传递”方式。,例:,main( ) y=fun( a0,a1.a2); float fun ( float a,float b,float c) float sum,aver; sum=a+b+c; aver=sum/3.0; return(aver); ,22,8.7 数组作为函数参数,2数组名作函数实参,此时,实参数组名和形参数组名都应 分别在各自所在的函数中定义;采取“地址 传送”方式,即:把实参数组的起始地址传 给形参数组,这样,实参数组和形参数组共 占同一段内存单元。,23,例:,main( ) float fun1(float x3); float a3=80.0,90.0,100.0; float ave; ave=fun1( a ); printf(“%fn”,ave); float fun1 ( float x3) float sum,aver; sum=x0+x1+x2; aver=sum/3.0; return(aver); ,24,例: 用函数调用实现字符串的复制。,void copy_string(from , to) char from , to ; int i = 0 ; while ( from i != 0 ) to i = from i ; i + + ; to i = 0 ; main( ) char a = “I am a teacher.” ; char b = “you are a student.” ; copy_string( a , b) ; printf( “string_a = %snstring_b = %sn”,a,b); ,运行结果: string_a = I am a teacher. string_b = I am a teacher.,25,8.8 局部变量和全局变量,1局部变量,在一个函数内部定义的变量,只能在本函数内使用和有 效,称为“局部变量”。, 主函数main中定义的变量, 也只能在主函数内使用和有效。, 不同函数中可以使用相同名字的变量,且互不干扰。, 形式参数也是局部变量, 也只能在所在函数内使用和有效。, 可以在一个函数内的复合语句中定义变量, 且这些变量只 在本复合语句中有效。,这种复合语句也称为 “分程序” 或 “子模块”。,2全局变量,在函数(包括main函数)外定义的变量为外部变量,称为 “全局变量”。全局变量的有效范围为从定义变量的位置开始 到本源文件结束。,26, 全局变量增加了函数间数据联系的渠道。由于同一文件中的所 有函数都能引用全局变量的值,当需要从一个函数中带回多个 值时,就能克服函数调用只能返回一个值的局限性。, 如无必要,不要使用全局变量。因为全局变量既降低程序的清 晰性和函数的通用性, 且又在程序的全部执行过程中都占用存 储空间。, 在文件开头定义的外部变量才可在整个文件范围内使用,若在 定义点之前的函数需引用外部变量,则可用关键字“extern”作 “外部变量说明”。,注意: 外部变量定义和外部变量说明并不是同一回事。外部变量 的定义只能有一次, 它的位置在所有函数之外。而同一程序中的外 部变量说明可以有多次,它的位置在函数之内 (哪个函数要用就在 哪个函数中说明)。系统根据外部变量的定义(而不是根据外部变量 的说明)分配存储单元。对外部变量的初始化只能在“定义”时进行, “extern”只是申明该变量是一个已在外部定义过的变量而已。, 如果在同一源文件中,外部变量与局部变量同名,则在局部变 量的作用范围内,外部变量不起作用。,27,例: #include “stdio.h” main( ) int a=1, b=2, c=3; a+; c+=b; int b=4, c; c=2b; a+=c; printf(“%d,%d,%dn”, a, b, c ); printf(“%d,%d,%dn”, a, b, c ); ,输出结果: 10, 4, 8 10, 2, 5,28,8.9 变量的存储类别,1动态存储方式与静态存储方式,静态变量在程序的运行期间占用固定的存储空间, 直到程序的终止而释放; 动态变量是在程序的运行期间随着函数的调用随时 动态地占用和释放存储空间。 存储方式是根据变量的存储类别决定的。,C的存储类别有四种:,自动的 (auto) 静态的 (static)、 寄存器的 (register) 外部的 (extern)。,29,8.9 变量的存储类别,1)自动变量(auto),自动变量是局部变量,2局部变量的存储方式,函数中的局部变量若未专门说明,都是由编译系统自 动动态分配存储空间,这类局部变量称为自动变量, 其类型说明前不论是否有关键字 “auto”, 都属于动态 存储类别。,自动变量赋值之前,值不确定,对同一函数的两次调用之间,自动变量的值不保留,定义式:auto数据类型 变量名=初值表达式1,,30,8.9 变量的存储类别,2)静态变量(static):局部变量,2局部变量的存储方式,静态变量的存储空间在程序 的整个运行期间时固定,定义式:static 数据类型 变量名表,若希望被调函数在结束后,其局部变量占用的存储空间不释放,以便保留其变量的值,用于下次调用该函数,则用“static”说明为 “局部静态变量”。,静态变量的初始化是在编译时进行的。,31, 局部静态变量在静态存储区分配存储单元,在程序的整个运行 期间都不释放。而动态变量在动态存储区分配存储单元,函数 调用结束后即释放。, 局部静态变量在编译时只赋初值一次,以后每次被调用时不再 重新赋值而只保留前次被调用结束时的值。动态变量赋初值不 是在编译时而是在函数被调用时进行的,函数每次被调用时重 新赋值,相当于赋值语句。, 静态变量若未赋初值,则在编译时自动赋初值0 (数值型)或空字 符(字符型)。而动态变量若未赋初值,则其值是不确定的。, 只有将数组定义为全局变量或静态变量时才能赋初值。但应注 意,如果数组的值在函数被调用过程中改变了,则影响下一次 调用时的初值。, 虽然局部静态变量在函数被调用结束后其值仍然存在,但其它 函数是不能引用的。,32,8.9 变量的存储类别,3)寄存器变量(register):局部变量,注意: 只有局部自动变量和形式参数可作为 是寄存器变量;静态变量和全局变量 均不行。,2局部变量的存储方式,特点: 速度快,一般把使用频率较高的变量 定义为寄存器变量。,定义式: register 数据类型 变量名表,33,例8.18 打印 1 到 5 的阶乘值。,int fac(n) int n; static int f =1; f = f n ; return( f ); main( ) int i; for (i=1; i=5; i+) printf(“%d!=%dn”, i, fac(i); ,3全局变量的存储方式,在文件开头用extern作说明,可以引用另一个文件 中定义的全局变量。但用static说明的全局变量不能被 其它文件引用。,34,int m=1,n=4; float f1(a) int a; int b,c; char ch1,ch2; char f2(x,y) int x,y; int k,j; main( ) extern int p,q; ,例:,35,全局变量的作用范围:,在文件开头定义的外部变量,在整个文件中均可以引用;,不在文件开头定义的外部变量,从定义点到 文件结束。,设置全局变量的作用

温馨提示

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

评论

0/150

提交评论