收藏 分享(赏)

C语言函数.ppt

上传人:gnk289057 文档编号:8291352 上传时间:2019-06-18 格式:PPT 页数:74 大小:1.39MB
下载 相关 举报
C语言函数.ppt_第1页
第1页 / 共74页
C语言函数.ppt_第2页
第2页 / 共74页
C语言函数.ppt_第3页
第3页 / 共74页
C语言函数.ppt_第4页
第4页 / 共74页
C语言函数.ppt_第5页
第5页 / 共74页
点击查看更多>>
资源描述

1、殷成凤,高级语言程序设计,主要内容,概述 函数定义的一般形式函数参数和函数的值函数的调用 函数的嵌套调用局部变量和全局变量变量的存储类别 内部函数和外部函数,主要内容,已知一个数,求其平方根 y=sqrt(100.0) 已知底数x,幂指数y,求xy z=pow(x,y) 求一个字符串的长度n=strlen(str1) 比较两个字符串的大小i=strcmp(str1,str2) 把字符串转换为相应的整数i=atoi(str1),y=f(x),函数的定义和调用,定义函数max,求两个参数a和b中较大的值。,说明:(1)一个程序由一个或多个程序模块组成,每一个程序模块作为一个源程序文件。对于较大的程

2、序,通常将程序内容分别放在若干个源文件中,再由若干源程序文件组成一个C程序。这样便于分别编写、分别编译,提高调试效率。一个源程序文件可以为多个C程序公用。,(2) 一个源程序文件由一个或多个函数以及其他有关内容(如命令行、数据定义等)组成。一个源程序文件是一个编译单位,在程序编译时是以源程序文件为单位进行编译的,而不是以函数为单位进行编译的。,(3) 程序的执行是从main函数开始的,如果在main函数中调用其他函数,在调用后流程返回到main函数,在main函数中结束整个程序的运行。,(4) 所有函数都是平行的,即在定义函数时是分别进行的,是互相独立的。一个函数并不从属于另一函数,即函数不能

3、嵌套定义。函数间可以互相调用,但不能调用main函数。main函数是系统调用的。,(6) 从函数的形式看,函数分两类: 无参函数。无参函数一般用来执行指定的一组操作。在调用无参函数时,主调函数不向被调用函数传递数据。 有参函数。主调函数在调用被调用函数时,通过参数向被调用函数传递数据。,(5) 从用户使用的角度看,函数有两种: 标准函数,即库函数。这是由系统提供的,用户不必自己定义这些函数,可以直接使用它们。不同的C系统提供的库函数的数量和功能会有一些不同,但许多基本的函数是共同的。 用户自己定义的函数。用以解决用户的专门需要。,函数定义的一般形式,无参函数的定义一般形式,定义无参函数的一般形

4、式为: 类型标识符 函数名() 声明部分语句部分,有参函数定义的一般形式,定义有参函数的一般形式为: 类型标识符 函数名(形式参数表列) 声明部分语句部分,空函数,定义空函数的一般形式为: 类型标识符 函数名() ,主调函数调用空函数时,只表明这里要调用一个函数,但函数本身什么工作也不做等,以后扩充函数功能时补充上。,函数参数和函数的值,形式参数和实际参数,形式参数:函数名后面括号中的变量名称为“形式参数”(简称“形参”)。 实际参数:主调函数中调用一个函数时,函数名后面括号中的参数(可以是一个表达式)称为“实际参数”(简称“实参”)。 函数返回值:return后面的括号中的值作为函数带回的值

5、(称函数返回值)。,函数的执行,(1)初始化max (2)传递参数 (3)保存当前现场,(1)接受函数返回值 (2)恢复现场,从断点处继续执行,主调函数和被调用函数之间有数据传递的关系。在不同的函数之间传递数据,可以使用的方法有: 参数:形式参数 实际参数 返回值:用return语句返回计算结果 全局变量:外部变量,关于形参与实参的说明:,(1) 在定义函数中指定的形参,在未出现函数调用时,它们并不占内存中的存储单元。只有在发生函数调用时,函数max中的形参才被分配内存单元。在调用结束后,形参所占的内存单元也被释放。,(2) 实参可以是常量、变量或表达式, 例如:max(,); 但要求它们有确

6、定的值。在调用时将实参的值赋给形参。,(3)在被定义的函数中,必须指定形参的类型。,(4)实参与形参的类型应相同或赋值兼容。,(5)值传递:实参向形参的数据传递是单向“值传递”,只能由实参传给形参,而不能由形参传回来给实参。在调用函数时,给形参分配存储单元,并将实参对应的值传递给形参,调用结束后,形参单元被释放,实参单元仍保留并维持原值。,17,参数的传递,参数的值传递举例。,改变形参变量的值,不影响实参变量,18,参数的传递,(2)实参可以是变量、常量或表达式。swap(3,4) /实参为常量swap(a+1,b+1) /实参是表达式,19,实参的取值顺序(),实参表列中包括了多个实参,在不

7、同的C语言编译系统中对求实参的先后次序不一定相同 在Visual C+中实参是按照先右后左的顺序取值。,参数取值的先后次序。,20,实参的取值顺序(),将上述程序的main()函数修改如下,程序的运行结果相同,但程序的可读性增强,21,函数返回值,函数类型和返回值。,通过函数调用,可使两个函数中的数据发生联系。,函数的返回值,函数的返回值是通过函数调用使主调函数得到的确定值。 例如:max(,)的值是,max(,)的值是5。赋值语句将这个函数值赋给变量。,说明: (1)函数的返回值是通过函数中的return语句获得的。一个函数中可以有一个以上的return语句,执行到哪一个return语句,哪

8、一个语句起作用。 return语句后面的括弧也可以不要 例如: “return ;” 等价于 “return ();” return后面的值可以是一个表达式。 例如: (int ,int ) return(?:); ,(2)函数的返回值应当属于某一个确定的类型,在定义函数时指定函数返回值的类型。例如:下面是3个函数的首行: int max(float ,float ) /* 函数值为整型 */ char letter(char c1,char c2) /* 函数值为字符型 */ double min(int ,int ) /* 函数值为双精度型 */,注意: 凡不加类型说明的函数,自动按整型处

9、理。,(3)在定义函数时指定的函数类型一般应该和return语句中的表达式类型一致。如果函数值的类型和return语句中表达式的值不一致,则以函数类型为准。对数值型数据,可以自动进行类型转换。即函数类型决定返回值的类型。,(4)对于不带回值的函数,应当用“void”定义函数为“无类型”(或称“空类型”)。此时在函数体中不得出现return语句。,函数的调用,函数调用的一般形式,函数调用的一般形式为: 函数名(实参表列),说明: (1)如果是调用无参函数,则“实参表列”可以没有,但括弧不能省略。,(3)如果实参表列包括多个实参,对实参求值的顺序并不是确定的,有的系统按自左至右顺序求实参的值,有的

10、系统则按自右至左顺序。,(2)如果实参表列包含多个实参,则各参数间用逗号隔开。实参与形参的个数应相等,类型应匹配。实参与形参按顺序对应,一一传递数据。,函数调用的方式,函数语句 把函数调用作为一个语句。这时不要求函数带回值,只要求函数完成一定的操作。,函数表达式 函数出现在一个表达式中,这种表达式称为函数表达式。这时要求函数带回一个确定的值以参加表达式的运算。 例如:*(,);,按函数在程序中出现的位置来分,可以有以下三种函数调用方式:,函数参数 函数调用作为一个函数的实参。 例如: m = max (a , max ( b , c ) ) ; 其中max ( b , c )是一次函数调用,它

11、的值作为max另一次调用的实参。m的值是a、b、c三者中的最大者。,在一个函数中调用另一函数(即被调用函数)需要具备哪些条件呢 ?,1.首先被调用的函数必须是已经存在的函数(是库函数或用户自己定义的函数)。但光有这一条件还不够。,3.如果使用用户自己定义的函数,而该函数的位置在调用它的函数(即主调函数)的后面,应该在主调函数中对被调用的函数作声明。,2.如果使用库函数,还应该在本文件开头用#include 命令将调用有关库函数时所需用到的信息“包含”到本文件中来。,函数原型的一般形式为: 1. 函数类型 函数名(参数类型1,参数类型2); 2. 函数类型 函数名(参数类型1,参数名1,参数类型

12、2,参数名2);,声明的作用是把函数名、函数参数的个数和参数类型等信息通知编译系统,以便在遇到函数调用时,编译系统能正确识别函数并检查调用是否合法。,注意:函数的“定义”和“声明”的区别:函数的定义是指对函数功能的确立,包括指定函数名,函数值类型、形参及其类型、函数体等,它是一个完整的、独立的函数单位。函数的声明的作用则是把函数的名字、函数类型以及形参的类型、个数和顺序通知编译系统,以便在调用该函数时系统按此进行对照检查。,数组作为函数的参数传递,行为 类似于简单变量的参数传递,在编译过程中形参、实参分配不同的存储单元,进行的是值传递,传递的方式为单向传递方式,1、数组元素作为函数参数,mai

13、n(),swap(a,b),a0,a1,a,b,数组作为函数的参数传递,行为 实现的是地址传递,形参获得的是实参数组的首地址。形参与实参共用一段地址,2、数组名作为函数参数,函数定义模式: 函数类型 函数名(形参数组类型 形参数组名),main(),swap(a),a2,a,以数组作为函数参数,(1)实参数组名表示数组的第0个元素的地址,即首地址。实参数组和形参数组的数据类型必须一致 (2)数组参数是地址传递,它们共用同一段内存,(3)形参数组定义为“int a10;”,其中数组长度可以省略。因此函数可以定义为: void setvalue(int x)、void output(int x)、

14、int sum(int x),40,以数组作为函数参数,排序完插入数据,设计 函数 1:函数 sort采用选择法对一数组的数进行排序2:函数Insert实现插入数的排序,以数组作为函数参数插入排序法,插入排序法思想: 1、数组a0是一个升序数组,a1为待插入元素,位置空闲,将x插入到升序数组a0中,使得a0a1升序 2、a2作为待插入元素,a2位置空闲,将x插入到升序数组a0a1中,使得a0a2升序3、ai作为待插入元素,ai位置空闲,将x插入到升序数组a0ai-1中,使得a0ai升序 .,多维数组作为函数参数,二维数组做函数参数与一维数组做函数参数相似 二维数组的形参定义时可以省略最左边维的

15、长度 二维数组做实参时也以数组名做实参 数组名代表二维数组的首地址,使得形参数组和实参数组共用同一段内存。 对形参数组的任何改变,也同样影响实参。,二维数组做形参 函数定义模式: 函数类型 函数名(形参数组类型 形参数组名),行数可以不指定 列数必须指定,二维数组作为函数参数,二维数组做形参示例:矩阵的转置,字符串作为函数参数,1、字符串作为函数参数时,形参数组定义为字符型数组,char s100 2、字符串以0作为结束标志,故字符串不需要数组长度,char s 3、实参则以字符串数组名为参数。,45,字符串作为函数参数,【例8. 12】编写函数能够将两个字符串连接起来。,实验七 1题,1题:

16、读写函数功能是:将M行N列的二维数组中的字符数据按列的顺序依次放到一个字符串中,并输出到屏幕(用Puts()函数),scanf的用法:1、空白字符空白字符会使scanf()函数在读操作中略去输入中的一个或多个空白字符,空白符可以是space,tab,newline等等,直到第一个非空白符出现为止。 2、非空白字符一个非空白字符会使scanf()函数在读入时剔除掉与这个非空白字符相同的字符。,函数的嵌套调用,嵌套定义:就是在定义一个函数时,其函数体内又包含另一个函数的完整定义 。 函数不可以嵌套定义,即一个函数定义中不能包含另一个函数的定义。 函数可以嵌套调用,即函数a调用函数b,函数b还可以调

17、用函数c,函数的嵌套调用,函数的递归调用,在调用一个函数的过程中又出现直接或间接地调用该函数本身,称为函数的递归调用。语言的特点之一就在于允许函数的递归调用。,简单示例:有个人坐在一起,问第个人多少岁?他说比第个人大岁。问第个人岁数,他说比第个人大岁。问第个人,又说比第个人大岁。问第个人,说比第个人大岁。最后问第个人,他说是岁。请问第个人多大。,age(5)= age (4)+2 age(4)= age (3)+2 age(3)= age (2)+2 age(2)= age (1)+2 age(1)= 10 用数学公式表述如下: age(n)= 10 () age(n-1)+2 (),可以用一

18、个函数来描述上述递归过程:,用一个主函数调用age函数,求得第5人的年龄。,递归方法,递归方法是一种特殊的解决问题的方法。其方法是将要解决的问题分解成比原问题规模小的类似子问题。 而解决这个类似子问题时,又可以用到原有问题的解决方法,按照这一原则,逐步递推转化下去,最终将原问题转化成较小且已知解的子问题。,分解后的子问题必须与原问题相似 能用原方法解决问题 最终的子问题答案已知,递归方法,递归求解方法1、递推阶段:将原问题不断转化成子问题,逐步从未知向已知推进。2、回归阶段:从已知的问题出发,按照递推的逆过程,逐一求值回归,最后到达递归的开始,结束回归阶段,获得问题解。,2、用递归方法求!,求

19、!也可以用递归方法,即!等于!,而!。 可用下面的递归公式表示:! (,)()! (),必须要有结束条件!,55,函数的递归调用 (*),【例8. 14】用递归算法求n!。 分析,观察可知:n!=n*(n-1)!,(n-1)!=(n-1)*(n-2)!,3!=3*2!,2!=2*1,1!=1 递归过程可以总结为两个阶段: 1回推阶段:n!(n-1)!(n-2)! (n-3)! 3! 2! 1!。要求n!,依次回推,直到求1!=1。 2递推阶段:n! (n-1)! (n-2)! (n-3)! 3! 2! 1!。求得1!,再从右向左,依次递推,直到求出n!。,n=0或1是递归的结束条件,当n1时,

20、继续递归调用。 如果递归没有结束条件,那么将一直递归下去,直到系统资源耗尽 。,56,函数的递归调用 (*),57,递归与迭代,58,程序设计举例:汉诺塔问题,汉诺塔问题 问题 假设有三个分别命名为X,Y和Z的塔座,在塔座X上插有n个直径大小各不相同、依从小到大编号为1,2,n的圆盘。现要求将X轴上的n个圆盘移到塔座Z上,并按同样的顺序叠放。 移动时必须遵循以下规则: 每次只能移动一个圆盘; 圆盘可以插在X,Y和Z中的任一塔座上; 任何时候都不能将一个较大的圆盘压在较小的圆盘之上。,59,程序设计举例:汉诺塔问题,汉诺塔问题 分析 n=1时 将圆盘1从塔座X移到塔座Z。,函数,基本情形,60,

21、程序设计举例:汉诺塔问题,汉诺塔问题 分析 n1(n=3)时,1. 利用塔座Z为辅助塔座,将压在圆盘n之上的n-1个盘从塔座X移到塔座Y;(与原问题类似)2. 将圆盘n从塔座X移到塔座Z;3. 利用塔座X为辅助塔座,将塔座Y上的n-1个圆盘移动到塔座Z。(与原问题类似),1,2,3,要实现: move(3,X,Y,Z) 需进行:move(2,X,Z,Y) move 3 from X to Zmove(2,Y,X,Z),要实现: move(n,X,Y,Z) 需进行:move(n-1,X,Z,Y) move n from X to Zmove(n-1,Y, X,Z),61,程序设计举例:汉诺塔问题

22、,汉诺塔问题设计 1、move 函数:移动一个盘 把盘 n 从 X塔座移到 Z塔座,函数,2、hanoi 函数:移动n个盘的汉诺塔问题把 n 个盘从 X塔座移到 X塔座, X塔座作为辅助X塔座,63,局部变量,在一个函数内部定义的变量称为内部变量,即局部变量。 它只在本函数内部才能使用,而在函数以外不能使用这些变量,也就是它的作用范围只在函数内部。 局部变量主要包括自定义的局部变量、形式参数、复合语句中定义的变量,64,局部变量,65,全局变量,在一个源程序文件中,函数内部定义的变量为局部变量, 在函数外部定义的变量为外部变量,也称为全局变量。 全局变量可以被本文件中其他函数共用,它的作用范围

23、是从定义的位置开始直到本源文件结束。,66,全局变量,在局部变量与全局变量名相同时,优先使用局部变量。,67,全局变量,全局变量可以被源文件中定义的所有函数引用和赋值,所以全局变量的最终值是给全局变量的最后一次赋的值。各个函数之间除了使用参数传递数据外,还可以使用全局变量来传递数据。 全局变量的全部执行过程中都占用内存,而不是仅在需要时才开辟单元。 编写程序时,应该尽量避免使用全局变量。函数必须依赖全局变量,所以函数的通用性降低所有函数都可以改变全局变量的值,使得难以判断每个瞬间各个外部变来那个的值另外全局变量过多,也会降低程序的可读性。,68,变量的存储类别和生存期,从变量在程序执行过程中占

24、用存储单元的时间来分 : 动态存储方式:指当函数被调用时,系统为函数中定义的变量分配存储单元,当函数调用结束时,这些变量的存储单元被释放 静态存储方式:指在程序运行期间一直占有存储空间 内存中可供用户使用的存储空间可以分为三部分,69,变量的存储类别和生存期,动态存储方式的变量包括: (1)函数形式参数; (2)函数内部定义的变量。 在调用函数时,给其分配存储空间,在函数运行结束时释放空间。 (1) 全局变量全部存放在静态存储区中,在程序开始运行时就分配存储空间,程序执行完毕才释放。 (2) 局部变量在定义时如果使用关键字static,则其也为静态变量。 (3) 静态存储变量默认的初值为0,7

25、0,变量的存储类别和生存期,存储类型: 定义变量时,可以使用以下关键字定义其存储方式: (1)auto (2)stitic (3)register (4)extern,存储类型 数据类型 变量名1,变量名2,;,71,auto类型变量,用关键字auto定义函数的局部变量为动态存储方式,而局部变量默认就是动态存储方式,72,static声明静态局部变量,如果在定义局部变量时,使用关键字static则该变量为静态变量 静态变量在程序执行期间一直占用存储单元,它只初始化一次 在每次调用其所在过程时,变量并不重新初始化,而是继续使用上次调用结束时保留的值。,73,register变量(*),在C语言中,可以将频繁使用的变量定义为register变量,则该变量将存放在CPU的寄存器中,需要使用时不需要到内存中读取和写入 寄存器的速度远高于内存,从而可以显著提高程序运行效率,(1)只有局部变量和形参可以作为寄存器变量,而全局变量不能定义为寄存器变量。 (2)一个CPU中的寄存器数目有限,因此定义寄存器变量不能太多。 (3)静态局部变量不能定义为寄存器变量。例如以下定义错误:,提醒!,第11周星期五下午随堂考试,考试方式为机考,考试内容为函数以前所有的内容,请注意复习,有问题可以通过QQ进行询问,

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 企业管理 > 管理学资料

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报