第9章函数梁.ppt

上传人:本田雅阁 文档编号:2547436 上传时间:2019-04-06 格式:PPT 页数:65 大小:1.65MB
返回 下载 相关 举报
第9章函数梁.ppt_第1页
第1页 / 共65页
第9章函数梁.ppt_第2页
第2页 / 共65页
第9章函数梁.ppt_第3页
第3页 / 共65页
亲,该文档总共65页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述

《第9章函数梁.ppt》由会员分享,可在线阅读,更多相关《第9章函数梁.ppt(65页珍藏版)》请在三一文库上搜索。

1、第9章 函数,2,教学目标,描述 C 语言中的函数 掌握 C 语言中常见的内置函数 理解函数原型和函数的返回值 熟练掌握自定义函数的定义和调用 理解变量的作用域 理解变量的存储类型 理解两种参数传递的方式:传值、引用 熟悉带参函数的调用 熟练使用数组作为函数参数 作业 书p210的1、2、6实验p107的2、3,3,程序设计的艺术,三国演义中有这样一段描写: 懿问曰:“孔明寝食及事之烦简若何?”使者曰:“丞相夙兴夜寐,罚二十以上皆亲览焉。所啖之食,日不过数升。”懿顾谓诸将曰:“孔明食少事烦,其能久乎?” 此话音落不久,诸葛亮果然病故于五丈原。 “事无巨细”,“事必躬亲” 管理学的观点是极其排斥

2、这种做法的,认为工作必须分工,各司其职 其中的思想,在程序设计里也适用,4,int main(void) : 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; : ,为什么使用函数,重复多次的同一计算类型,int main(void) : ans1=cube(x,y,z); ans2=cube(a,b,c); : ,int cube(int a,int b,int c) int ans; ans=(a*a*a)+(b*b*b)+(c*c*c); return ans; ,函数,主程序,an

3、s,函数可以把相对独立的某个功能抽象出来,使之成为程序中的一个独立实体。可以在同一个程序或其他程序中多次重复使用,5,用函数解决问题的要点,分而治之 函数把较大的任务分解成若干个较小的任务,并提炼出公用任务 复用 程序员可以在其他函数的基础上构造程序,而不需要从头做起 信息隐藏 设计得当的函数可以把具体操作细节对程序中不需要知道它们的那些部分隐藏掉,从而使整个程序结构清楚,6,函数机制的优点,使程序变得更简短而清晰 有利于程序维护 可以提高程序开发的效率 提高了代码的重用性,7,C语言中的函数,说明: 一个源程序文件由一个或多个函数组成。 一个C程序由一个或多个源程序文件组成。 C程序的执行从

4、main函数开始,调用其他函数后流程回到main函数,在main函数中结束整个程序运行。 所有函数都是平行的,即函数定义时是互相独立的,一个函数并不从属于另一个函数。,8,函数类型,内置函数: 由语言系统提供; 用户无须定义,也不必在程序中作类型说明; 只需在程序前包含有该函数定义的头文件;,自定义函数: 用户在程序中根据需要而编写的函数;,9,常用内置函数,10,问题描述: 求自然数110的平方根和立方。,内置函数sqrt 和pow 示例,2,6,64,#include #include int main(void) int x=1; double squareroot,power; whi

5、le(x = 10) squareroot=sqrt(x); power=pow(x,3); printf(“ %d的平方根:%3.2ft%d的立方:%5.0f n“, x,squareroot,x,power); x+; return 0; ,1的平方根: 1.00 1的立方: 1 2的平方根: 1.41 2的立方: 8 3的平方根: 1.73 3的立方: 27 4的平方根: 2.00 4的立方: 64 5的平方根: 2.24 5的立方: 125 6的平方根: 2.45 6的立方: 216 7的平方根: 2.65 7的立方: 343 8的平方根: 2.83 8的立方: 512 9的平方根:

6、3.00 9的立方: 729 10的平方根: 3.16 10的立方: 1000 Press any key to continue,11,toupper和tolower示例,2,6,64,#include #include int main(void) char msg1,msg2,to_upper,to_lower; printf(“请输入一个小写字母:“); msg1=getchar(); to_upper=toupper(msg1); printf(“转换为大写:%cn“,to_upper); printf(“请输入一个大写字母:“); fflush(stdin); msg2=getch

7、ar(); to_lower=tolower(msg2); printf(“转换为小写:%cn“,to_lower); return 0; ,请输入一个小写字母:d 转换为大写:D 请输入一个大写字母:E 转换为小写:e Press any key to continue,12,内置函数rand示例,2,6,64,#include #include /#include int main(void) int i; printf(“产生 10 个 0 到 99 之间的随机数序列:nn“); / srand(unsigned)time(NULL); 取1970年1月1日到现在的秒数为随机种子 for

8、(i=0; i10; i+) printf(“%d “, rand() % 100); printf(“n“); return 0; ,产生 10 个 0 到 99 之间的随机数序列: 44 73 26 58 37 94 27 42 28 90 Press any key to continue,13,函数定义,如果没有参数,则应该用void注明 如果不需要返回值,则应该用void定义返回值类型 返回值类型与return语句配合 当函数执行到return语句时,就中止函数的执行,返回到调用它的地方 函数内部可以定义只能自己使用的变量,称内部变量。 参数表里的变量也是内部变量,14,函数命名规则

9、,Linux/Unix平台 习惯用function_name Windows风格函数名命名 用大写字母开头、大小写混排的单词组合而成 FunctionName 变量名形式 “名词”或者“形容词+名词” 如变量名oldValue与newValue等 函数名形式 “动词”或者“动词+名词”(动宾词组) 如函数名GetMax()等,15,对函数接口加以注释说明,/* 函数功能:实现功能 函数参数:参数1,表示 参数2,表示 函数返回值: */ 返回值类型 函数名(参数表) 函数体 return 表达式; ,16,计算两个整数的平均数,/* 函数功能: 计算平均数 函数入口参数: 整型x,存储第一个运

10、算数 整型y,存储第二个运算数 函数返回值: 平均数 */ int Average(int x, int y) int result; result = (x + y) / 2; return result; ,17,计算两个数的最大值,/* 函数功能: 计算最大值 函数入口参数: 实型x,存储第一个运算数 实型y,存储第二个运算数 函数返回值: 最大数 */ double max(double x, double y) double m; m=xy?x:y; return m; ,该函数名为max,它有两个double类型的参数,返回值为double类型。在函数体内有三条语句实现了求两个数中

11、较大的数,并将它返回。,18,计算打折函数,void displayDiscount() float price, discount_amt; printf(“请输入价格“); scanf(“%f, ,该函数名为displayDiscount,无参数,使用void说明无返回值,函数体内的语句用于根据产品的价格求折扣后的价格。,19,函数参数,形参( 形式参数 ): 在定义函数时,定义函数名后面括号中的变量名 实参( 实际参数 ): 在主调函数中调用一个函数,调用函数名后面括号中的参数(或表达式),20,函数调用,通过在程序中使用函数名称,可以执行函数中包含的语句,这称为调用函数 单向值传递 调

12、用函数时,必须提供所有的参数 printf和scanf是采用变长变量表定义的函数,所以变量的个数不固定。 提供的参数个数、类型、顺序应与定义时相同,21,函数调用,int main() int a = 12; int b = 24; int ave; ave = Average(a, b); printf(“Average of %d and %d is %d.n“, a, b, ave); return 0; ,22,函数调用,有返回值时 放到一个数值表达式中 如 c = max(a,b); 作为另一个函数调用的参数 如 c = max(max(a,b),c); printf(“%dn“,

13、max(a,b); 无返回值时 函数调用表达式 如 display(a,b);,23,函数原型,调用一个函数之前,先要对其返回值类型、函数名和参数进行声明(declare) 有助于编译器进行类型检查 函数原型说明在形式上与函数头部类似,最后加一个分号。原型说明中参数表里的参数名可以不写(只写参数类型)。 声明时不要省略参数以及返回值的类型,#include float count (int, int); int main(void) . . . . . . float count(int x,int y) . . . ,24,#include /* 函数功能: 计算平均数 函数入口参数: 整型

14、x,存储第一个运算数 整型y,存储第二个运算数 函数返回值: 平均数 */ int Average(int x, int y) int result; result = (x + y) / 2; return result; int main() int a = 12; int b = 24; int ave = Average(a, b); printf(“Average of %d and %d is %d.n“, a, b, ave); return 0; ,函数原型,25,#include int Average(int x, int y); /*声明Average()函数*/ int

15、 main() int a = 12; int b = 24; int ave = Average(a, b); printf(“Average of %d and %d is %d.n“, a, b, ave); return 0; /* 函数功能: 计算平均数 函数入口参数: 整型x,存储第一个运算数 整型y,存储第二个运算数 函数返回值: 平均数 */ int Average(int x, int y) int result; result = (x + y) / 2; return result; ,函数原型,26,函数之间允许相互调用,也允许嵌套调用 函数还可以自己调用自己,称为递归

16、调用,#include int main(void) : set_discount(); displayDiscount(); : : ,float set_discount() : : float displayDiscount() : : ,函数调用,27,void reverse() : : ,#include int main(void) : palindrome(); : : ,void palindrome() : reverse(); : ,函数嵌套调用,从一个函数调用另一个函数称为函数的嵌套调用,28,函数嵌套调用,main函数 调用函数 A; ,函数 A 调用函数 B; ,函

17、数 B ,调用,调用,返回,返回,29,函数递归调用,函数直接或间接的调用自身叫函数的递归调用,说明 C编译系统对递归函数的自调用次数没有限制 每调用函数一次,在内存堆栈区分配空间,用于存放函数变量、返回值等信息,所以递归次数过多,可能引起堆栈溢出,int f(int x) int y,z; z=f(y); . return(2*z); ,30,/* 此函数用于计算 a 的阶乘 */ int factorial(int a) if(a0) printf(“data error!“); else if (a=0 |a = 1) return 1; else a = a * factorial(a

18、-1); return a; ,函数递归调用,在一个函数体内调用自身称为函数的递归调用,31,函数递归调用,int main() int m; printf(“Input the number of disks:“); scanf(“%d“, ,void move(char getone, char putone) printf(“%c-%cn“,getone,putone); void hanoi(int n,char one,char two,char three) if(n=1) move(one,three); else hanoi(n-1,one,three,two); move(o

19、ne,three); hanoi(n-1,two,one,three); ,32,问题描述: 根据用户的选择求不同形状的面积。,函数调用示例,#include void AreaOfRect(); void AreaOfTriangle(); void AreaOfRound(); int main(void) int select; do printf(“ 0、退出n 1、长方形n 2、三角形n 3、圆形n“); printf(“请选择功能:“); scanf(“%d“, ,void AreaOfRect() int x,y; printf(“请输入长方形的长:“); scanf(“%d“,

20、 ,void AreaOfTriangle() int x,y; printf(“请输入三角形的底:“); scanf(“%d“, ,void AreaOfRound() int r; printf(“请输入圆形的半径:“); scanf(“%d“, ,函数原型,33,int divisibleCheck(int num) if (num % 5 = 0) return 1; else return 0; ,C语言中的函数至多可以返回一个值,不能返回多个值; 返回值的数据类型必须与函数原型中返回值的数据类型匹配; 当遇到 return 语句时,函数执行将终止。程序控制流将立即返回调用函数;,函

21、数返回值,C 语言中的 return 语句用于向调用函数返回值,语法如下: return ();,34,函数返回值示例,#include int get_age(); int main(void) int age1, age2, age3; age1 = get_age(); age2 = get_age(); age3 = get_age(); if ( (age1 age2) ,65,78,int get_age() int age; printf(“n请输入年龄: “); scanf(“%d“, ,请输入年龄:65,请输入年龄:78,请输入年龄:54,年龄为 78 岁的人最大,54,35

22、,变量的作用域,作用域是某些事物起作用或有效的区域。,限于陆地,限于海洋,限于空中,36,程序中变量也有不同的使用范围,称为变量的作用域。变量的作用域指在源程序中定义变量的位置及其能被读写访问的范围,变量的作用域,void displayDiscount() float discount_amt; . . . . . . . . . ,局部变量:不能在函数外使用,float discount_amt; int main() . . . . . . void displayDiscount() . . . . . . ,全局变量:可以在整个程序中使用,37,局部变量,主函数中定义的变量只能在主函

23、数中使用,不能在其它函数中使用。同时,主函数中也不能使用其它函数中定义的变量。因为主函数也是一个函数,它与其它函数是平行关系。 形参变量是属于被调用函数的局部变量,实参变量是属于主调函数的局部变量。 允许在不同的函数中使用相同的变量名,它们代表不同的对象,分配不同的单元,互不干扰,也不会发生混淆。,38,局部变量,在语句块内定义的变量 形参也是局部变量 特点 定义时不会自动初始化,除非程序员指定初值 进入语句块时获得内存,仅能由语句块内语句访问,退出语句块时释放内存,不再有效 并列语句块各自定义的同名变量互不干扰,39,全局变量,如果同一程序的多个函数都操纵同一个变量,全局变量比较有用。 外部

24、变量可加强函数模块之间的数据联系,但是又使函数要依赖这些变量,因而使得函数的独立性降低。从模块化程序设计的观点来看这是不利的,因此在不必要时尽量不要使用全局变量。 在同一源文件中,允许全局变量和局部变量同名。在同名的局部变量的作用域内,全局变量不起作用。,40,全局变量,在所有函数之外定义的变量 特点 在程序中定义它的位置以后都有效 在定义点之前或在其他文件中引用,应该进行如下声明: extern 类型名 变量名; 从程序运行起即占据内存,程序运行过程中可随时访问,程序退出时释放内存 使函数之间的数据交换更容易,也更高效 但是并不推荐使用,尽量少用 因为谁都可以改写全局变量,所以很难确定是谁改

25、写了它,41,变量的作用域,#include void addNumbers() int num1,num2,sum; printf(“n 请输入两个数:“); scanf(“%d %d“, ,0,45,请输入两个数:56 45,子函数中sum的值是101,主函数中sum的值是 0,56,101,42,变量的作用域,#include int sum=0; void addNumbers() int num1,num2; printf(“n 请输入两个数:“); scanf(“%d %d“, ,0,45,请输入两个数:56 45,子函数中sum的值是101,主函数中sum的值是101,56,10

26、1,43,变量的作用域,#include int a,b; void f1() float x,y; int f2() void main() ,不是所有全局变量都可以直接使用。 只有定义在该函数之前的全局变量, 才能在函数中使用。,44,存储类型,指数据在内存中存储的方式 即编译器为变量分配内存的方式,它决定变量的生存期 动态存储 根据需要临时分配存储空间,离开即释放 静态存储 在程序运行期间分配固定的存储空间不释放 静态存储变量是一直存在的,而动态存储变量则时而存在时而消失 这种由于变量存储方式不同而产生的特性称为变量的生存期 生存期表示了变量存在的时间,45,存储类型,程序区,静态存储区

27、,动态存储区,形参、自动变量、函数调用的现场等,全局变量、静态变量,46,存储类型,47,自动变量,“自动”体现在 进入语句块时自动申请内存,退出时自动释放内存 标准定义格式 auto 类型名 变量名; 动态局部变量 缺省的存储类型 不初始化时,值是不确定的,48,寄存器变量,寄存器 CPU的内部容量很有限、但速度极快的存储器 使用频率比较高的变量声明为register ,可以使程序更小、执行速度更快 register 类型名 变量名; register int i; 现代编译器有能力自动把普通变量优化为寄存器变量,并且可以忽略用户的指定,所以一般无需特别声明变量为register,49,静态

28、局部变量static,static静态局部变量生存期为整个源程序 静态局部变量作用域与自动变量相同,即只能在定义该变量的函数内使用该变量 对基本类型的静态局部变量若在说明时未赋以初值,则系统自动赋予0值 函数被调用时,其中的静态局部变量的值将保留前次被调用的结果,50,静态局部变量示例,void format() static int m = 0; m+; if (m % 10 = 0) putchar(n); else putchar( ); int main(void) int i; for(i=0;i50;i+) printf(“%d“,i); format(); return 0; ,

29、0,0,1,1,循环执行50次,49,49,0 1,0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49,2,51,静态全局变量,静态全局变量与普通全局变量在存储方式上完全相同 区别在于:非静态全局变量的作用域是整个源程序;而静态全局变量的作用域只是定义它的文件,52,函数形参和实参,int main (void ) . . . . . . display ( 10, 2

30、0.5 ); void display ( int num, float fraction ) . . . . . . ,实际参数,函数调用,形式参数,53,int main(void) int a = 0; /初始化a值为0 func(a); /调用函数func printf(“%d“,a); /输出a的结果 return 0; /定义函数func void func(int a) a = 10; /让参数a等于10 ,传值调用,0,传值调用,将会输出什么,54,#include void increment(int,int); int main(void) int num1,num2; p

31、rintf(“n 请输入两个数: “); scanf(“ %d %d“, ,传值调用示例,请输入两个数 :,34 56,递增前的值是 34 和 56,_,递增后的值是 34 和 56,34,56,子函数中的值是 35 和 57,35,34,56,57,55,传值调用示例,#include main() int x=7,y=11; printf(“x=%d,ty=%dn“,x,y); printf(“swapped:n“); swap(x,y); printf(“x=%d,ty=%dn“,x,y); swap(int a,int b) int temp; temp=a; a=b; b=temp;

32、 ,56,数组元素做函数参数值传递,例 两个数组大小比较,n=0 m=0 k=0,a和b为有10个元素的整型数组 比较两数组对应元素 变量n,m,k记录aibi, ai=bi, aik,认为数组ab 若nk,认为数组ab 若n=k,认为数组a=b,57,数组名做函数参数地址传递,在主调函数与被调函数分别定义数组,且类型应一致 形参数组大小(多维数组第一维)可不指定 形参数组名是地址变量,58,数组名做函数参数地址传递,例 求学生的平均成绩,#include float average(int stu10, int n); int main() int score10, i; float av;

33、 printf(“Input 10 scores:n“); for( i=0; i10; i+ ) scanf(“%d“, ,float average(int stu10, int n) int i; float av,total=0; for( i=0; in; i+ ) total += stui; av = total/n; return av; ,实参用数组名,形参用数组定义, int stu ,59,#include void swap2(int x,int y) int z; z=x; x=y; y=z; int main() int a2=1,2; swap2(a0,a1);

34、printf(“a0=%dna1=%dn“,a0,a1); return 0;,值传递,数组元素与数组名做函数参数比较,60,#include void swap2(int x) int z; z=x0; x0=x1; x1=z; int main() int a2=1,2; swap2(a); printf(“a0=%dna1=%dn“,a0,a1); return 0;,地址传递,数组元素与数组名做函数参数比较,61,总结4-1,函数是程序中的一个相对独立的单元或模块,程序在需要时可以任意多次地调用函数来完成特定功能 使用函数带来的好处: 程序更清晰、易维护、分模块方便设计与开发、提高代码

35、的重用性 语言提供了极为丰富的内置函数,这些内置函数分门别类地放在不同的头文件中,要使用这些内置函数,只要在程序前包含相应的头文件即可,62,总结4-2,自定义函数是用户在程序中根据需要而编写的函数 函数的结构包括:返回值类型、函数名、参数列表、函数体 函数原型说明以便向编译器指出该函数使用什么样的格式和语法 函数调用时程序控制流将转向被调函数,被调函数执行结束时,控制流返回主调函数 return 语句用于向调用函数返回值,63,总结4-3,根据变量的作用域可以将变量划分为:局部变量和全局变量 根据变量的存储类型(决定生存期)将变量划分为: 自动变量、寄存器变量、静态变量、外部变量 静态局部变量的生存期为整个源程序,但其作用域为定义该变量的函数 静态全局变量的生存期为整个源程序,其作用域为定义该变量的源文件,64,总结4-4,采用传值调用方式时,在被调用函数中改变形参的值,只是改变其副本值,而不会影响调用函数中实参值 采用引用调用方式时,传递的是变量的地址值,这样在被调函数中,对形参的操作实际上操作的是实参本身 数组作为函数传递时,实际采用引用调用方式,65,Thank you,Question?,

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

当前位置:首页 > 其他


经营许可证编号:宁ICP备18001539号-1