学期C程序设计(第三版)教材-第8章-2讲稿.ppt_第1页
学期C程序设计(第三版)教材-第8章-2讲稿.ppt_第2页
学期C程序设计(第三版)教材-第8章-2讲稿.ppt_第3页
学期C程序设计(第三版)教材-第8章-2讲稿.ppt_第4页
学期C程序设计(第三版)教材-第8章-2讲稿.ppt_第5页
已阅读5页,还剩50页未读 继续免费阅读

下载本文档

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

文档简介

,第八章,函数,8.1概述8.2函数定义的一般形式8.3函数参数和函数的值8.4函数的调用8.5函数的嵌套调用8.6函数的递归调用8.7数组作为函数参数8.8局部变量和全局变量简8.9变量的存储类别*8.10内部函数和外部函数,主要内容,语言不能嵌套定义函数,但可嵌套调用函数,即在调用一个函数的过程中,又调用另一个函数。,8.函数的嵌套调用,例8.用弦截法求方程f(x)=x3-5x2+16x-80=0的根,8.函数的嵌套调用,取两个不同点x1,x2,如果f(x1)和f(x2)符号相反,则(x1,x2)区间内必有一个根。如果f(x1)与f(x2)同符号,则应改变x1,x2,直到f(x1)、f(x2)异号为止。注意x1、x2的值不应差太大,以保证(x1,x2)区间内只有一个根。(2)连接(x1,f(x1)和(x2,f(x2)两点,此线(即弦)交x轴于x,方法:,(3)若f(x)与f(x1)同符号,则根必在(x,x2)区间内,此时将x作为新的x1。如果f(x)与f(x2)同符号,则表示根在(x1,x)区间内,将x作为新的x2。,(4)重复步骤(2)和(3),直到f(x)一个很小的数,例如1e-6.此时认为f(x)0,例8.用弦截法求方程f(x)=x3-5x2+16x-80=0的根,8.函数的嵌套调用,方法:,N-S流程图,例8.用弦截法求方程f(x)=x3-5x2+16x-80=0的根,8.函数的嵌套调用,分别用几个函数来实现各部分功能:,(1)用函数f(x)代表x的函数:x3-5x2+16x-80.(2)调用函数xpoint(x1,x2)求(x1,f(x1)和(x2,f(x2)的连线与x轴的交点x的坐标。(3)调用函数root(x1,x2)求(x1,x2)区间的实根。执行root函数要用到函数xpoint,而执行xpoint函数过程中要用到f函数。,例8.用弦截法求方程f(x)=x3-5x2+16x-80=0的根,8.函数的嵌套调用,#include#includefloatf(floatx)/*函数实现f(x)=x3-5x2+16x-80=0*floaty;=(x-5.0)*x+16.0)*x-80.0;returny;floatxpoint(floatx1,floatx2)*xpoint函数求弦与x轴交点*/floaty;y=(x1*f(x2)-x2*f(x1)/f(x2)-f(x1);returny;floatroot(floatx1,floatx2)/*root函数求近似根*/floatx,y,y1;y1=f(x1);dox=xpoint(x1,x2);y=f(x);if(y*y1)y1=y;x1=x;elsex2=x;while(fabs(y)=0.0001);returnx;,例8.用弦截法求方程f(x)=x3-5x2+16x-80=0的根,voidmain()floatx1,x2,f1,f2,x;doprintf(inputx1,x2:n);scanf(f,%f,x1,x2);f1f(x1);f2f(x2);while(f1*f2);root(x1,x2);printf(“rootofequationis%8.4n”,);,运行情况如下:inputx1,x2:2,6rootofequationis.0000,例8.用弦截法求方程f(x)=x3-5x2+16x-80=0的根,函数直接或间接的调用自身叫函数的递归调用。,8.6函数的递归调用,例如:intf(intx)inty,z;z=f(y);.return(2*z);,入栈,f1调用f2;f2调用f3;f3调用f4;f4调用f5.,8.6函数的递归调用,说明:C编译系统对递归函数的自调用次数没有限制,每调用函数一次,在内存堆栈区分配空间,用于存放函数变量、返回值等信息,所以递归次数过多,可能引起堆栈溢出。,递归算法:在可计算性理论中占有重要地位,它是算法设计的有力工具,对于拓展编程思路非常有用。我们先从一个最简单的例子导入:,用递归算法求n!定义:函数fact(n)=n!fact(n-1)=(n-1)!则有fact(n)=n*fact(n-1)已知fact(1)=1,8.6函数的递归调用,用递归算法求n!定义:函数fact(n)=n!fact(n-1)=(n-1)!则有fact(n)=n*fact(n-1)已知fact(1)=1,从图可以想象:欲求fact(3),先要求fact(2);要求fact(2)先求fact(1)。就象剥一颗圆白菜,从外向里,一层层剥下来,到了菜心,遇到1的阶乘,其值为1,到达了递归的边界。然后再用fact(n)=n*fact(n-1)这个普遍公式,从里向外倒推回去得到fact(n)的值。,8.6函数的递归调用,调用和返回的递归示意图,#includeintfac(intn)floatf;if(n0)printf(“nbi,ai=bi,aibn”);elseif(nk)printf(“ay)flag=1;elseif(xy)flag=-1;elseflag=0;return(flag);,例8.10两个数组大小比较,a,b,x,y,8.数组作为函数参数,数组名可作函数参数,此时形参应当用数组名或用指针变量。,例8.11有一个一维数组score,内放10个学生成绩,求平均成绩。,8.7.2数组名作函数参数,8.数组作为函数参数,#includevoidmain()floataverage(floatarray10);/*函数声明*/floatscore10,aver;int;printf(input10scores:);for(i=0;i10;i+)scanf(,scorei);printf(n);averaverage(score);printf(averagescoreis5.2n,aver);,floataverage(floatarray10)int;floataver,sumarray0;for(i=1;i10;i+)sumsumarrayi;aversum/10;return(aver);,运行情况如下:input10scores:100567898.576879967.57597averagescoreis83.40,例8.12形参数组不定义长度,#includevoidmain()floataverage(floatarray,int)floatscore_1598.5,97,91.5,60,55;floatscore_210=67.5,89.5,99,69.5,77,89.5,76.5,54,60,99.5;printf(“theaverageofclassAis%6.2fn”,average(score_1,5);printf(“theaverageofclassBis%6.2fn”,average(score_2,10);floataverage(floatarray,int)int;floataver,sum=array0;for(;)sumsumarrayi;aversum;return(aver);,运行结果如下:theaverageofclassAis80.40Theaverageofclassis78.20,8.数组作为函数参数,注意:实参数组和形参数组类型要一致,C编译系统对形参数组大小不作检查。,array,score_1,a0a1a2a3a436194未排序时的情况16394将5个数中最小的数1与a0对换13694将余下的4个数中最小的数3与a1对换13496将余下的3个数中最小的数4与a2对换13469将余下的2个数中最小的数6与a3对换,至此完成排序,例8.13用选择法对数组中10个整数按由小到大排序。,8.数组作为函数参数,#includevoidmain()voidsort(intarray,int);inta10,i;printf(enterthearray);for(i=0;i10;i+)scanf(,ai);sort(a,10);printf(thesortedarray);for(i=0;i10;i+)printf(,ai);printf(n);voidsort(intarray,int)inti,j,k,t;for(i=0;in-1;i+)=;for(j=i+1;jn;j+)if(arrayarray)=;=arrayk;arrayk=arrayi;arrayi=t;,例8.13用选择法对数组中10个整数按由小到大排序。,8.7.3.多维数组名作函数参数,例8.4#includevoidmain()max_value(intarray4);inta34=1,3,5,7,2,4,6,8,15,17,34,12;printf(maxvalueis,max_value(a));max_value(intarray4)/*形参数组第2维长度不可省*/inti,j,k,max;max=array00;for(i=0;imax)max=arrayij;return(max);,运行结果如下:Maxvalueis34,8.数组作为函数参数,在一个函数内部定义的变量是内部变量,只在本函数范围内有效,称为“局部变量”。,8.8.1局部变量,8.8局部变量和全局变量,floatf1(inta)/*函数f1*/intb,c;a、b、c有效charf2(intx,inty)/*函数f2*/inti,j;x、y、i、j有效voidmain()/*主函数*/intm,n;m、n有效,说明:(1)主函数中定义的变量只在主函数中有效,主函数也不能使用其他函数中定义的变量。(2)不同函数中可以使用相同名字的变量,它们在内存中占不同的单元,代表不同的对象,互不干扰。(3)形参也是局部变量,只在本函数中有效。(4)在一个函数内部,可以在复合语句中定义变量,这些变量只在本复合语句中有效,这种复合语句也称为“分程序”或“程序块”。,8.8.1局部变量,8.8局部变量和全局变量,voidmain()inta,b;intc;c=a+b;/*a,b,c在此范围内有效*/,在函数之外定义的变量称为外部变量,外部变量是全局变量(也称全程变量)。全局变量可以为本文件中其他函数所共用。它的有效范围为从定义变量的位置开始到本源文件结束。,8.8.2全局变量,8.8局部变量和全局变量,intp=1,q=5;/*外部变量*/floatf1(inta)/*定义函数f1*/intb,c;charc1,c2;/*外部变量*/charf2(intx,inty)/*定义函数f2*/inti,j;voidmain()/*主函数*/intm,n;,全局变量p,q的作用范围,全局变量c1,c2的作用范围,例8.15有一个一维数组,内放10个学生成绩,写一个函数,求出平均分、最高分和最低分。,#includefloatMax,Min;*习惯定义全局变量首字母大写*voidmain()floataverage(floatarray,intn);floatave,score10;int;for(i=0;i10;i+)scanf(%f,scorei);ave=average(score,10);printf(“max=%6.2fnmin=%6.2fnaverage=%6.2fn“,Max,Min,ave);,8.8.2全局变量,8.8局部变量和全局变量,floataverage(floatarray,intn)*定义函数,形参为数组*/int;floataver,sum=array0;Max=Min=array0;for(=;)if(arrayiMax)Maxarrayi;elseif(arrayiMin)Minarrayi;sum=sum+arrayi;aversum;return(aver);,运行情况如下:9945789710067.589926643max100.00min43.00average77.65,说明:1、全局变量增加了函数间数据的联系渠道。2、建议不在必要时不要使用全局变量,原因如下:,全局变量在程序的执行过程中都占用存储单元。使用全局变量过多,会降低程序的清晰性,人们难以清楚地判断出每个瞬时各外部变量的值。函数的通用性降低。如将一个函数移到另一个文件中,还要将有关的外部变量及其值一起移过去。但若该外部变量与其他文件的变量同名时,就会出问题。3、同一源文件中外部变量与局部变量同名则在局部变量的作用域内外部变量不起作用。,8.8局部变量和全局变量,例8.16外部变量与局部变量同名,#includeinta=3,b=5;/*a,b为外部变量*/a,b作用范围voidmain()inta=8;/*a为局部变量*/局部变量a作用范围printf(%d,max(a,b);全局变量b的作用范围max(inta,intb)/*a,b为局部变量*/intc;c=ab?ab;形参a、b作用范围return(c);,运行结果为8,8.8局部变量和全局变量,从变量的作用域角度来分:全局变量和局部变量。那么从变量值存在的时间(即生存期)角度来分:静态存储方式和动态存储方式。,静态存储方式是程序运行期间由系统分配固定的存储空间的方式。动态存储方式是程序运行期间根据需要动态的分配存储空间的方式。存储空间可以分为三部分:程序区静态存储区:(如:全局变量)动态存储区:(函数形参、自动变量、函数调用的现场保护和返回地址),8.变量的存储类别,8.9.1动态存储方式与静态存储方式,中每一个变量和函数有两个属性:数据类型和数据的存储类别。存储类别指的是数据在内存中存储的方式。存储方式分为:静态存储类和动态存储类。具体包含四种:自动的(auto),静态的(static),寄存器的(register),外部的(extern)。根据变量的存储类别,可以知道变量的作用域和生存期。,8.变量的存储类别,8.9.1动态存储方式与静态存储方式,函数中的局部变量,如不专门声明为static存储类别,都是动态地分配存储空间的,数据存储在动态存储区中。函数中的形参和在函数中定义的变量(包括在复合语句中定义的变量),都属此类,在调用该函数时系统会给它们分配存储空间,在函数调用结束时就自动释放这些存储空间。因此这类局部变量称为自动变量。用关键字auto作存储类别的声明。例如:int(int)*定义f函数,为形参*autoint,;*定义、为自动变量*,8.变量的存储类别,8.9.2auto变量,如希望函数中的局部变量在函数调用结束后占用的存储单元不释放,下一次该函数被调用时,用到上一次函数调用结束时局部变量的值。应指定该局部变量为“静态局部变量”,用static声明。,8.变量的存储类别,8.9.3用static声明局部变量,例8.17考察静态局部变量的值。#includevoidmain()intf(int);inta=2,i;for(i=0;i3;i+)printf(%d,f(a);intf(inta)autointb=0;staticc=3;b=b+1;c=c+1;return(a+b+c);,对静态局部变量的说明:(1)静态局部变量属静态存储类别,在静态存储区内分配存储单元。在程序整个运行期间都不释放。而动态局部变量(即自动变量)属动态存储类别,占动态存储区空间,函数调用结束后即释放。(2)对静态局部变量是在编译时只赋一次初值,程序运行时已有初值。以后每次调用函数时不再重新赋初值而只保留上次函数调用结束时的值。而对自动变量是在函数调用时赋初值,每调用一次函数重新给一次初值。,8.变量的存储类别,(3)如定义变量时不赋初值,则对静态局部变量,编译时自动赋初值(对数值型变量)或空字符(对字符变量)。而对自动变量因每次函数调用结束后释放存储单元,下次调用时另分配存储单元,单元中的值不确定。(4)虽然静态局部变量在函数调用后仍存在,但其他函数不能引用它。,例8.18输出到的阶乘值。#includevoidmain()intfac(int);int;for(i=1;iy?x:y;return(z);,1.在一个文件内声明外部变量,2.在多文件的程序中声明外部变量,例8.21用extern将外部变量的作用域扩展到其他文件。本程序的作用是给定的值,输入A和,求A和Am的值。文件file1.c中的内容为:#includeintA;/*定义外部变量*/voidmain()intpower(int);/*函数声明*/int3,c,d,m;printf(enterthenumberaanditspowerm:n);scanf(,A,);A*;printf(*n,A,b,c);power(m);printf(*nA,m,d);,8.变量的存储类别,文件file2.c中的内容为:externA;/*声明A为一个已定义的外部变量*/intpower(intn)int,;for(i=1;i=n;i+)*A;return(y);,8.9.6用static声明外部变量,有时希望限定某些外部变量只限于被本文件引用。可在定义外部变量时加一个static声明。例如:file1.cfile2.cstaticintA;externintA;/*无效扩展*/voidmain()voidfun(intn)A=A*n;,8.变量的存储类别,8.9.7关于变量的声明和定义,对变量而言,声明与定义的关系稍微复杂一些。在声明部分出现的变量有两种情况:一种是需要建立存储空间的“定义性声明”或简称定义(如:inta;),另一种是不需要建立存储空间的“引用性声明”(如:externa;)。广义地说,声明包括定义,但并非所有的声明都是定义。对“inta;”而言,它既是声明,又是定义。而对“externa;”它是声明而不是定义。,8.变量的存储类别,一般为叙述方便,把建立存储空间的声明称定义,而把不需要建立存储空间的声明称为声明。例如:voidmain()externA;/*是声明不是定义。声明A是一个已定义的外部变量*/intA;,(1)从作用域分,有局部变量和全局变量。它们采用的存储类别如下:局部变量|动态局部变量,即自动变量(离开函数,值就消失)|静态局部变量(离开函数,值仍保留)|寄存器变量(离开函数,值就消失)|(形式参数可以定义为自动变量或寄存器变量)全局变量|静态外部变量(只限本文件引用)|外部变量(即非静态的外部变量,允许其他文件扩展引用),8.变量的存储类别,8.9.8存储类别小结,8.变量的存储类别,(2)从变量存在的时间(生存期)分:动态存储和静态存储。静态存储是程序整个运行时间都存在,而动态存储则是在调用函数时临时分配单元。动态存储|自动变量(本函数内有效)|寄存器变量(本函数内有效)|形式参数(本函数内有效)静态存储|静态局部变量(函数内有效)|静态外部变量(本文件内有效)|外部变量(其他文件可引用),8.9.8存储类别小结,(3)从变量值存放的位置分,可分为:内存中静态存储区|静态局部变量|静态外部变量(函数外部静态变量)|外部变量(可为其他文件引用)内存中动态存储区:自动变量和形式参数CPU中的寄存器:寄存器变量,(4)关于作用域和生存期的概念。前者是从空间的角度,后者是从时间的角度。二者有联系但不是同一回事。(5)static对局部变量和全局变量的作用不同。对局部变量,它使变量由动态存储方式改变为静态存储方式。对全局变量,它使变量局部于本文件,但仍为静态存储方式。从作用域角度看,凡static声明的,其作用域都是局限的,或者是局限于本函数内(静态局部变量),或局限于本文件内(静态外部变量)。,8.9.8存储类别小结,8.变量的存储类别,函数本质上是全局的,但也可指定函数不能被其他文件调用。根据函数能否被其他源文件调用,将函数区分为内部函数和外部函数。,如一个函数只能被本文件中其他函数所调用,它称为内部函数。定义内部函数一般形式:static类型标识符函数名(形参表)如:staticintfun(inta,intb),8.10内部函数和外部函数,8.10.1内部函数,8.

温馨提示

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

评论

0/150

提交评论