C语言程序设计基础 第7章-函数

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

2020/1/301第7章函数与预处理命令7.1概述7.2函数的定义与调用7.3数组作函数参数7.4函数的嵌套调用和递归调用7.5局部变量和全局变量及其作用域7.6变量的存储类别及变量的生存期7.7函数的存储分类2020/1/3027.1概述①程序结构清晰,可读性好。②减少重复编码的工作量。③可多人共同编制一个大程序,缩短程序设计周期,提高程序设计和调试的效率。使用函数的好处……C程序源程序文件n函数1函数m……源程序文件1函数1函数n2020/1/303【例7.1】求一个整数的立方。intcube(intx)/*函数定义*/{return(x*x*x);}main(){intf,a;printf(\nEnteranintegernumber:);scanf(%d,&a);f=cube(a);printf(%d*%d*%d=%d\n,a,a,a,f);}程序运行情况如下:Enteranintegernumber:22*2*2=8函数调用程序的执行总是从main函数开始2020/1/304⑴一个C源程序可以由一个或多个源程序文件组成。C编译系统在对C源程序进行编译时是以文件为单位进行的。⑵一个C源程序文件可以由一个或多个函数组成。所有函数都是独立的。主函数可以调用其它函数,其它函数可以相互调用。⑶在一个C程序中,有且仅有一个主函数main。C程序的执行总是从main函数开始,调用其它函数后最终回到main函数,在main函数中结束整个程序的运行。说明2020/1/305⑷函数的种类从函数定义形式分:①有参函数:在主调(用)函数和被调(用)函数之间通过参数进行数据传递,如:intcube(intx){…}②无参函数:如:getchar()在调用无参函数时,主调函数不需要将数据传递给无参函数。从使用的角度看:①标准函数(库函数)库函数是由系统提供的。如:getchar()、sin(x)等。在程序中可以直接调用它们。附录A列出了C的部分库函数。②用户自定义函数。如:例7.1中的cube函数。2020/1/3067.2.1函数的定义函数定义的一般形式函数类型函数名(类型名形式参数1,…){说明语句执行语句}例如:求两个数的最大值。intmax(intx,inty){intz;z=xy?x:y;return(z);}类型省略时默认为int类型没有形式参数为无参函数2020/1/307intmax(x,y)intx,y;{intz;z=xy?x:y;return(z);}intmax(x,y){intx,y;……}或intmax(intx,y){……}或intmax(x,y)intx,y,z;{z=xy?x:y;return(z);}花括号中也可以为空,这种函数叫空函数。不能在函数体内定义其他函数,即函数不能嵌套定义。形参也可以这样定义如下定义都是错误的√2020/1/308函数名(实参表列)在C语言中,把函数调用也作为一个表达式。因此凡是表达式可以出现的地方都可以出现函数调用。例如:①welcome();②if(iabs(a)max)max=iabs(a);③m=max(c,max(a,b));7.2.2函数的调用函数调用的一般形式:2020/1/309intsum100(){inti,t=0;for(i=1;i=100;i++)t+=i;return(t);}main(){ints;s=sum100();printf(%d\n,s);}程序输出结果:5050intsum(intx){inti,t=0;for(i=1;i=x;i++)t+=i;return(t);}main(){ints;s=sum(100);printf(%d\n,s);}【例7.3】求1~100的累加和。思考:两个程序有何不同程序输出结果:50502020/1/3010voidswap(intx,inty){intz;z=x;x=y;y=z;printf(\nx=%d,y=%d,x,y);}main(){inta=10,b=20;swap(a,b);printf(\na=%d,b=%d\n,a,b);}7.2.3函数参数与函数的返回值1.函数的形式参数与实际参数程序输出结果:x=20,y=10a=10,b=20形式参数(形参)实际参数(实参)【例7.4】编一程序,将主函数中的两个变量的值传递给swap函数中的两个形参,交换两个形参的值。单向值传递2020/1/3011有关形参和实参的说明:①当函数被调用时才给形参分配内存单元。调用结束,所占内存被释放。②实参可以是常量、变量或表达式,但要求它们有确定的值。③实参与形参类型要一致,字符型与整型可以兼容。④实参与形参的个数必须相等。在函数调用时,实参的值赋给与之相对应的形参。“单向值传递”。注意:在TC中,实参的求值顺序是从右到左。2020/1/3012【例7.8】计算并输出圆的面积。s(intr){return3.14*r*r;}main(){intr,area;scanf(%d,&r);printf(%d\n,s(r));}自动转换为int型思考:若要得到单精度实型的圆面积,程序应如何修改程序运行情况如下:2122020/1/30137.2.4对被调函数的声明和函数原型变量要先定义后使用,函数也如此。即被调函数的定义要出现在主调函数的定义之前。如swap函数:允许整型函数(且参数也是整型)的定义出现在主调函数之后。如max函数:如果非整型函数在主调函数之后定义,则应在主调函数中或主调函数之前对被调函数进行声明。voidswap(intx,inty){…}main(){…swap(a,b);}main(){…c=max(a,b);}max(intx,inty){…}2020/1/30147.3.2一维数组名作函数参数数组名表示数组在内存中的起始地址。例如:数组a在内存中从2000地址开始存放,则a的值为2000。2000是地址值,是指针类型的数据(第8中将介绍指针类型),不能把它看成是整型或其他类型数据。实参是数组名,形参也应定义为数组形式,形参数组的长度可以省略,但[]不能省,否则就不是数组形式了。【例7.12】用冒泡法将10个整数排序。2020/1/3015voidsort(intb[],intn);voidprintarr(intb[]);main(){inta[10]={11,22,63,97,58,80,45,32,73,36};printf(Beforesort:\n);printarr(a);sort(a,10);printf(Aftersort:\n);printarr(a);}voidprintarr(intb[10]){inti;for(i=0;i10;i++)printf(%5d,b[i]);printf(\n);}voidsort(intb[],intn){inti,j,t;for(i=1;in;i++)for(j=0;jn-i;j++)if(b[j]b[j+1]){t=b[j];b[j]=b[j+1];b[j+1]=t;}}2020/1/3016a[0]a[1]a[2]a[3]a[4]a[5]a[6]a[7]a[8]a[9]b[0]b[1]b[2]b[3]b[4]b[5]b[6]b[7]b[8]b[9]11226397588045327336(a)排序前a[0]a[1]a[2]a[3]a[4]a[5]a[6]a[7]a[8]a[9]b[0]b[1]b[2]b[3]b[4]b[5]b[6]b[7]b[8]b[9]11223236455863738097(b)排序后图7.3调用sort函数2000b形参b实际是一个可以存放地址的变量a:2000实参赋给形参首地址:2000首地址:20002020/1/3017以二维数组为例。二维数组名作实参时,对应的形参也应该定义为一个二维数组形式。对形参数组定义时可以指定每一维的大小,也可以省略第一维的大小说明。【例7.14】编程序,将矩阵转置。设转置前为a矩阵,转置后为b矩阵,如下所示:a=123456789101112159261037114812b=思路:将a[0][0]b[0][0],a[0][1]b[1][0],a[0][2]b[2][0],a[1][0]b[0][1],…,a[i][j]b[j][i],…。7.3.3多维数组作函数参数2020/1/30187.4.2函数的递归调用1.递归的基本概念递归调用:一个函数直接或间接地调用了它本身,就称为函数的递归调用。递归函数:在函数体内调用该函数本身。intsub(intx){inty,z;……if(……)z=sub(y);else{……}return;}例如:直接调用sub函数本身2020/1/30192.递归函数的执行过程【例7.16】编一递归函数求n!。思路:以求4的阶乘为例:4!=4*3!,3!=3*2!,2!=2*1!,1!=1,0!=1。递归结束条件:当n=1或n=0时,n!=1。递归公式:n!=1(n=0,1)n×(n-1)!(n1)2020/1/3020递归调用过程回推main()fact(4)fact(3)fact(2)fact(1){{{{{……………y=fact(4);f=4*fact(3);f=3*fact(2);f=2*fact(1);f=1;……………return24return6return2return1}}}}}递推2020/1/30213.编制递归函数的方法⑴数值型问题递归函数的编程方法对于数值型问题,首先要找出解题的数学公式,这个公式必须是递归定义的,且所处理的对象要有规律地递增或递减,然后确定递归结束条件。【例7.17】编一递归函数求xn。思路:首先把xn转化成递归定义的公式xn=1(n=0)x×xn-1(n0)再找出递归结束条件:当n=0时,xn=1。2020/1/3022程序如下:longxn(intx,intn){longf=0;if(n0)printf(n0,dataerror!\n);elseif(n==0)f=1;elsef=x*xn(x,n-1);return(f);}main(){intn,x;longy;scanf(%d,%d,&x,&n);y=xn(x,n);printf(%ld\n,y);}程序运行情况如下:2,1010242020/1/30237.5.3全局变量及其作用域全局变量(外部变量):在函数外部定义的变量。作用域:从定义变量的位置开始到本源文件结束。如在其作用域内的函数或分程序中定义了同名局部变量,则在局部变量的作用域内,同名全局变量暂时不起作用。【例7.20】全局变量和局部变量的作用域。2020/1/30247.6.2变量的存储类别变量的属性数据类型:决定为变量分配内存单元的长度,数据的存放形式,数的范围。存储类别:决定了变量的生存期,给它分配在哪个存储区。2020/1/3025变量定义语句的一般形式存储类别数据类型变量名1,…,变量名n;auto(自动的)register(寄存器的)static(静态的)extern(外部的)1.自动变量(auto类别)局部变量可以定义为自动变量。main(){intx,y;…}main(){autointx,y;…}自动变量等价可省2020/1/3026⑴内存分配调用函数或执行分程序时在动态存储区为其分配存储单元,函数或分程序执行结束,所占内存空间即刻释放。⑵变量的初值定义变量时若没赋初值,变量的初值不确定;如果赋初值则每次函数被调用时执行一次赋值操作。⑶生存期在函数或分程序执行期间。⑷作用域自动变量所在的函数内或分程序内。自动变量2020/1/30272.静态变量(static类别)除形参外,局部变量和全局变量都可以定义为静态变量。局部静态变量(或称内部静态变量)全局静态变量(或称外部静态变量)静态变量静态变量staticinta;main(){floatx,y;…}f(){staticintb=1;……}全局静态变量局部静态

1 / 34
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功