Lifang20131/44操作系统#includestdio.hmain(){charc=‘A’;c+=32;printf(“%c”,c);…}库函数printf()函数调用Lifang20132/44操作系统对一些常用的功能,希望象使用scanf(),printf()那样调用现成的模块来实现,从而使得程序结构更清晰、避免代码重复。——可以自己定义函数sort();#includestdio.hmain(){准备一组数据;排序函数调用(冒泡…);输出排序后的数据;}voidSort(){…}Lifang20133/44操作系统第6章引例函数的定义和调用递归函数数组与函数*程序的多文件组织作用域及存储类型*函数的存储类型函数Lifang20134/44操作系统模块化程序设计•函数如何定义•函数如何使用•调用函数时,数据如何传递#includestdio.hmain(){inta,b;intz;scanf(“%d%d”,&a,&b);if(ab)z=a;elsez=b;printf(“%d”,z);}#includestdio.hintmax(intx,inty){intz;if(xy)z=x;elsez=y;retutn(z);}main(){inta,b,z;scanf(“%d%d”,&a,&b);z=max(a,b);printf(“%d”,z);}6.1引例P94Lifang20135/44操作系统函数定义语法:返回类型函数名(形参表){说明语句;执行语句…;return(表达式)}6.2.1函数的定义P953)函数需要返回值时,用return语句。不需要时则不必使用。return(表达式)或return表达式4)函数中可能有多条return语句,但只能有一条被执行.5)函数不允许嵌套定义,函数之间是平行的。函数头函数体2)函数的返回类型可以省略,默认为int函数的返回类型也可以是void型,表示无返回值1)形参表语法:(类型参数名,类型参数名……)形参表也可为空——无参函数intmax(intx,inty)例{intz;if(xy)z=x;elsez=y;retutn(z);}Lifang20136/44操作系统6.2.2函数的调用P96•函数的调用语法–函数名(实参,实参,……)main()例{inta,b,z;scanf(“%d%d”,&a,&b);z=max(a,b);printf(“%d”,z);}说明:1)函数的调用在语法上相当于一个表达式,可构成表达式语句或作为另一个表达式的操作数或作为流程控制语句的组成部分。2)函数调用时的实参个数、类型应与函数定义中的形参个数、类型相吻合;形参是函数定义时的参数,是变量;仅在调用函数时,才为形参分配内存;调用结束后,形参所占内存马上释放实参是函数调用时的参数,可以是常量、变量或表达式——是一个“值”。3)调用的函数必须是已经定义了的函数。4)函数的调用是可以嵌套的;两个名词:主调函数(主函数,子函数)被调函数(子函数)Lifang20137/44操作系统函数的调用流程:以引例为例:①主调函数向被调函数传递:在调用子函数时发生。以实参的方式向形参提供参数:②子函数向主调函数传递:在被调函数即将执行完毕时发生。将结果return回主调函数每次只能return一个值。12主调函数被调函数Lifang20138/44操作系统例:编写函数,求一个数的阶乘,在主函数中调用该函数。#includestdio.hintJC(intx){inti,s=1;for(i=1;i=x;i++)s*=i;returns;}main(){intn,res;scanf(%d,&n);res=JC(n);printf(%d,res);}Lifang20139/44操作系统#includestdio.hintJC(intx){inti,s=1;for(i=1;i=x;i++)s*=i;returns;}main(){intn,res;scanf(%d,&n);res=JC(n);printf(%d,res);}#includestdio.hmain(){intn,res;scanf(%d,&n);res=JC(n);printf(%d,res);}intJC(intx){inti,s=1;for(i=1;i=x;i++)s*=i;returns;}intJC(intx);Lifang201310/44操作系统6.2.3函数的存在性说明(函数声明)P98返回类型函数名(形参表);#includestdio.hmain(){intn,res;intJC(intx);scanf(%d,&n);res=JC(n);printf(%d,res);}intJC(intx){inti,s=1;for(i=1;i=x;i++)s*=i;returns;}intJC(int);说明:1)存在性说明也称为函数原型(prototype),系统利用函数原型对函数的合法性进行检查。Error:Function…shouldhaveaprototype!3)常见库函数的原型:见附录CP192看到函数原型就应该知道函数的调用方法2)库函数的原型在.h文件中Lifang201311/44操作系统6.3函数的递归调用P100函数直接或间接地调用自身称为递归调用。例:计算n!intFN(intn){if(n=1)return1;returnn*FN(n-1);}main(){intn;floaty;printf(inputainteagernumber:\n);scanf(%d,&n);ifn0printf(“DataError!”)y=FN(n);printf(%d!=%ld\n,n,y);getch();}n!=n*(n-1)!Lifang201312/44操作系统以计算3!为例,调用a=FN(3);a=FN(3);n为3if(n=1)return1;returnn*FN(n-1);n为2if(n=1)return1;returnn*FN(n-1);n为1if(n=1)return1;returnn*FN(n-1);返回1返回2(2*1)返回6(3*2)Lifang201313/44操作系统递归三要素:–递归形式:FN(n)–递归规则:n*(n-1)!–递归终结条件:n=1intFN(intn){if(n=1)return1;returnn*FN(n-1);}递归调用的实质就是将原来的问题分解为新的问题,而解决新问题时又用到了原有问题的解法。按照这一原则分解下去,每次出现的新问题都是原有问题的简化的子问题,而最终分解出来的问题,是一个已知解的问题。这就是有限的递归调用。只有有限的递归调用才是有意义的,无限的递回调用永远得不到解,没有实际意义。Lifang201314/44操作系统汉诺塔问题假设三个塔,第一个塔上有从小到大堆积的一叠金属片,一次从一个塔搬运一片到另一个塔,只能从塔顶搬运,不允许大的金属片压在小的金属片上,求解将金属片全部搬运到第三个塔上的过程及搬运次数Lifang201315/44操作系统递归解决–递归形式:hannoi(intn,inta,intb,intc)n:片数a:起点塔号,b:中间塔号,c:目标塔号–递归规则:先将n-1片搬运到中间塔上;将最后一片搬运到目标塔上;将n-1片从中间塔上搬运到目标塔上;–递归终结条件:当n=1时,直接搬运;Lifang201316/44操作系统程序代码#includestdio.hvoidhanoi(intn,inta,intb,intc){if(n==1){printf(Movechip%dfromtower%dtotower%d\n,n,a,c);}else{hanoi(n-1,a,c,b);printf(Movechip%dfromtower%dtotower%d\n,n,a,c);hanoi(n-1,b,a,c);}}main(){intn;printf(“HanoiProblem:\nPleaseinputthenumberofdiskes:);scanf(%d,&n);hanoi(n,1,2,3);return0;}Lifang201317/44操作系统6.4数组作函数的参数P103#includestdio.hvoidmain(){inta[10]={4,7,9,1,54,67,88,2,21,3};floatave;floataverage(inta[10]);/*函数声明*/ave=average(a);/*将数组a传递给average*/printf(%7.2f,ave);}floataverage(intm[10])/*数组作函数的参数*/{inti,sum=0;for(i=0;i10;i++)sum+=m[i];returnsum/10.0;}6.4.1一维数组作参数例6-8:求10名学生的平均成绩Lifang201318/44操作系统例6-9:计算一组整数中偶数的个数,偶数判断用函数实现P101#includestdio.hvoidmain(){inta[10]={4,7,9,1,54,67,88,2,21,3};inti,s=0;floateven_num(inta[10]);for(i=0;i10;i++)s+=even_num(a[i]);printf(%d,s);}floateven_num(intn)/*数组作函数的参数*/{if(n%2==0)return1;elsereturn0;}Lifang201319/44操作系统6.4.2函数间的参数传递主调函数向被调函数传递时形参和实参可有两种类型:1.可以是简单数据类型——“值传递”,res=JC(n);n为整型变量s+=even_num(a[i]);a[i]为数组元素,也是整型变量2.也可以是地址(数组,指针)——“地址传递”。ave=average(a);a为数组名(即数组的首地址,代表数组)Lifang201320/44操作系统6.4.3二维数组作为函数参数#includestdio.hvoidmain(){inta[3][3]={1,2,3,4,5,6,7,8,9};intmain_max(ints[3][3]);intres;res=main_max(a);printf(主对角线元素最大值为%d\n,res);}intmain_max(ints[3][3])/*二维数组作函数的参数*/{inti;intm=s[0][0];for(i=1;i3;i++)if(s[i][i]m)m=s[i][i];returnm;}例6-11编写函数求已知二维矩阵主对角线上元素的最大值Lifang201321/44操作系统例6-12编写函数求一已知二维矩阵中各行元素的最大值P107#includestdio.hvoidmain(){inta[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};intm[3];/*用于存放结果*/inti;voidrow_max(ints[3][4],intres[3]);row_max(a,m);for(i=0;i3;i++)printf(第%d行最大值为%d\n,i+1,m[i]);}Lifang201322/44操作系统voidrow_max(ints[3][4],intres[3]){inti,j;for(i=0;i3;i++){res[i]=s[i][0];for(j=1;j4;j++)if(s[i][j]res[i])res[i]=s[i][j];/*将结果通过res写入主调函数的m*/}}接上页Lifang201323/44操作系统6.4.4字符数组作为函数参数#includestdio.hvoidmain(){chars[100];intn;intNum(chars[100]);ge