




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
程序设计是计算机学科关键和灵魂程序设计基础第四章函数1/991回想函数主函数:intmain(){cout<<"ComputerScience.\n";return0;}库函数:#include<math.h>intmain(){floata,b,c,x1,x2;cin>>a>>b>>c;x1=(-b+sqrt(b*b-4.*a*c))/(2*a);x2=(-b-sqrt(b*b-4.*a*c))/(2*a);cout<<x1<<x2;return0;}2/9924.1c++语言函数什么是函数?独立程序段执行一个详细、明确定义任务易于编写、了解、调试和维护将需要屡次执行一组指令定义为函数程序结构清楚,可读性好,易于维护代码代码能够重用,降低重复编码工作量可多人共同编制一个大程序,缩短程序设计周期,提升程序设计和调试效率。函数功效3/993函数建立与使用函数建立
函数申明:定义函数名字、执行语句序列、传递和使用数据参数、返回值等;函数使用
函数调用:指明函数去“做什么”;4/994一个程序由一个或多个源程序文件组成一个源程序文件由一个或多个函数组成程序执行从main函数开始,并回到main函数结束函数之间能够相互调用,或调用本身不能调用main函数函数之间相互独立,不存在隶属关系全部函数都能够调用库函数必须起点main()f1()f2()f3()f11()f12()f21()f22()f31()5/995intmain(void){inta,b,c;cin>>a>>b;c=max(a,b);cout<<c;}intmax(intx,inty){intz;z=x>=y?x:y;return(z);}主函数函数体函数类型,返回值类型函数名(用标识符命名),引用函数标志,并得到结果。函数参数说明表。定义!调用!函数定义是要确定函数名称、函数类型、函数参数及函数功效。intmax(intx,inty);6/996函数分类(1)从用户角度标准函数(库函数):C++语言集成开发环境提供,存放在库函数中,用户链接对应库函数头文件后便能够直接使用。用户自定义函数:由用户按照逻辑功效自己编写程序(2)从函数形式无参函数:调用该函数时,主调函数不需函数要将数据传递给被调用函数,只执行指定一组操作
有参函数:主调需传递数据给被调函数(3)从函数返回值角度:有返回值函数和无返回值函数7/9974.2函数定义与调用函数类型
函数名(函数参数定义){ 说明部分(变量申明)
语句部分
return结果;}intmax(intx,inty){intz;z=x>=y?x:y;return(z);}intmax(intx,inty){…intcx(intc,intd){…}/*Error!*/…}函数定义不能够嵌套一、函数定义普通格式8/9981)函数类型:函数返回值类型。指数据类型,如:int,float,double,bool,char,void等等。假如函数没有返回值,应指明返回类型void。假如函数类型省略,系统默认类型为int型。提倡显示指明函数类型
和变量命名一样,是标识符函数名后一定要有一对圆括号(),这是函数标志,使函数与其它标识符名区分开来尽可能要能够表示出正确意义。函数名重在说明它要“做什么”。2)函数名:intmax(intx,inty){intz;z=x>=y?x:y;return(z);}9/9994)函数体函数体用一对{}包含。里面就是函数用以实现功效代码。申明部分:用于申明在函数中使用到变量语句部分:在函数中用于实现某项任务语句序列空函数:函数体为空(没有语句,但{}不能省略intmax(intx,inty){intz;z=x>=y?x:y;return(z);}10/99105)return语句
return语句只在函数内使用.它起到让函数停顿运行,然后返回一个值作用,并返回到函数调用程序下一条语句。函数体里能够有多个return语句,也能够没有return语句,或者写不带结果return语句。return返回结果,类型普通和前面“返回类型”一致。假如不一致,系统自动将表示式类型转换为函数类型。
intmax(intx,inty){intz;z=x>=y?x:y;return(z);}intmax(inta,intb){
if(a>b)returna;
returnb;}11/99116)函数类型,return,及怎样获取函数返回值
intmax(intx,inty)函数类型:即函数返回值类型.intmax(inta,intb){return(a>b)?a:b;}intmax(floata,floatb){return(a>b)?a:b;}return语句让函数停顿运行,返回一个值intmax(inta,intb){
if(a>b)returna;
returnb;}若函数是void类型时,return不能接返回值,return仅起结束函数作用return后可接表示式、变量、常量、甚至也能够接一个函数调用表示式获取函数返回值intc=max(10,7)12/9912二、函数参数——形式参数函数形式参数定义:
普通格式:(数据类型变量1,数据类型变量2,……)多个参数之间用逗号隔开,而不是分号,且最终一个变量之后则不需要符号。两个或多个参数类型相同时,并不能同时申明intmax(intx,y)
用于接收从主调函数传给这个函数数据形参个数不受限制,能够很多,也能够无intmax(intx,inty){intz;z=x>=y?x:y;return(z);}形式参数:函数在申明或定义时,所写出参数定义。13/9913形参只是形式上参数,所以在申明一个函数时,甚至能够不写形参变量名:函数申明能够写为:intmax(int,int);在自定义函数中指定形参变量,在未出现函数调用时,它们并不占用内存中存放单元.只有在发生函数调用时形参才被分配内存单元.在调用结束后,所占用存放单元被释放.形参必须指定参数类型二、函数参数——形式参数14/9914intmax(x,y){intx,y;……}或intmax(intx,y){……}或intmax(x,y)intx,y,z;{z=x>y?x:y;return(z);}形参也能够这么定义以下定义都是错误
√不过不推荐intmax(x,y)intx,y;{intz;z=x>y?x:y;return(z);}二、函数参数——形式参数15/9915出现在函数调用表示式中,是函数调用时,实际使用参数普通形式:(表示式1,表示式2,……)实际参数表是用逗号分隔表示式列表,其中每个表示式称为实际参数,简称为实参,能够是常量,变量或表示式函数调用时,需将实际参数值传送给对应位置形式参数实际参数与形式参数必须一一对应,位置、个数以及数据类型都匹配二、函数参数——实际参数16/9916
形式参数:定义函数时,函数名后()中参数实际参数:调用函数时函数名后()中表示式intmain(void){inta,b,c;cin>>a>>b;c=max(a,b);cout<<c;}intmax(intx,inty){intz;z=x>=y?x:y;return(z);}实参形参c=max(a,b);(main函数)(max函数)max(intx,inty){intz;z=x>y?x:y;return(z);}二、函数参数——形式参数与实际参数intmax(intx,inty);17/9917实参必须有确定值实参能够是常量、变量、表示式、函数调用形参必须指定类型形参加实参类型一致,个数相同若形参加实参类型不一致,自动按形参类型转换———函数调用转换形参在函数被调用前不占内存;函数调用时为形参分配内存;调用结束,内存释放二、函数参数——形式参数与实际参数18/9918三、函数调用函数调用普通形式:看成表示式使用 函数名(实际参数表)假如是调用无参函数,则“实参表列”能够没有,但括弧不能省函数调用方式:普通调用方式有三种:语句形式:max(a,b);/*不要求函数带回值*/表示式形式:c=max(a,b)*2;/*函数是表示式一部分*/函数参数:c=max(a,max(b,d));/*函数调用作为一个函数实参*/函数调用作为一个表示式,其类型是函数返回值类型函数调用可用于任何表示式能够出现地方在调用一函数过程中,又调用另一函数C++允许函数嵌套调用,不允许函数嵌套定义19/9919voidmain(void){inta,b,c;cin>>a>>b;
c=max(a,b);cout<<c;}intmax(intx,inty){intz;z=x>y?x:y;return(z);}⑴先计算实参值,从右向左(或者从左向右)向函数传递调赋值给形参。23abXy23⑵转移到函数中运行,执行到return语句,将返回表示式值。由函数名带回给调用函数。z3三、函数调用intmax(intx,inty);20/9920函数调用执行过程:1、程序在执行过程中一旦碰到一个函数调用,系统首先为每个形参分配一定数目标存放单元(存放单元字节数由参数类型决定);然后计算实参表示式值,并将实参值送到形参对应存放单元中(实参加形参按位置对应);
2、将执行控制转移到被调用函数第一个执行语句处开始执行,直到函数体末尾或碰到一个return语句为止;
3、当执行到函数体末尾或执行return语句时,假如函数有返回值,则将控制返回到调用点同时返回一个值,这个返回值就是函数调用表示式值;不然只返回控制。
控制返回到调用函数之后从函数调用点继续向后执行。21/9921四、函数申明(函数原型)函数使用必须遵照“先申明、后使用”标准,因为C++编译系统在编译时必须先知道该函数实现形式(接口形式)。在一个函数中调用另一个函数需要具备条件.⑴被调用函数必须已经存在(库函数或用户自定义函数)⑵若使用库函数,要在本文件开头用#include命令将调用相关库函数时所需用到信息“包含”到本文件中来.#include<math.h>⑶假如使用用户自定义函数,且该函数与调用它函数(主调函数)在同一个文件中,则要在主调函数中对被调用函数作申明.函数申明经过”函数原型”给出。22/9922对于用户自定义函数假如被调用函数定义位于主调函数后面,则必须在调用函数表示式之前对被调用函数做引用性申明函数定义性申明:完整、独立函数单位,包含函数类型、函数名、形参及其类型,而且含有完整函数体;函数引用性申明(函数原型):无函数体部分,普通形式:函数定义首部;函数原型必须与函数定义保持一致四、函数申明(函数原型)23/9923以下情况能够省去对被调函数说明:假如被调用函数定义位置或对其进行类型说明位置在调用函数之前;假如被调用函数不在调用函数所在源文件中,但用#include包含了被调用函数所在文件函数原型普通形式为:函数类型函数名(参数类型1,参数类型2……);函数类型函数名(参数类型1,参数名1,参数类型2,参数名2……);intmax(inta,intb);intmax(int,int);intmax(intx,inty);简单了解为函数定义时第一行+;四、函数申明(函数原型)24/9924写一程序,实现求长方形,三角形,圆形,梯形面积,要求各种形状分别用一个函数处理。程序大致流程是:首先提问用户要求什么形状态面积?然后依据用户输入,使用一个switch语句区分处理,分别调用对应函数.求不一样形状态面积,需要用户输入不一样数据,基于本程序结构,我们认为将这些操作也封装到各函数比较适当。实例一:25/9925intmain(){
charch; do{ cout<<"面积函数"<<endl; cout<<"0、退出"<<endl <<"1、长方形"<<endl
<<"2、三角形"<<endl <<"3、圆形"<<endl <<"4、梯形"<<endl; cin>>ch; if(ch=='0')break; switch(ch) { case'1':AreaOfRect();break; case'2':AreaOfTriangle();break; case'3':AreaOfRound();break; case'4':AreaOfTrape();break;//梯形
default:cout<<"请在0~4之间选择"<<endl; } }while(true);}
voidAreaOfRect(){
intx,y;
cout<<"请输入长方形长:";
cin>>x;
cout<<"请输入长方形宽:";
cin>>y;
cout<<"面积为:"<<(x*y)<<endl;}26/9926五、内联函数intmain(void){ for(inti=1;i<10;i++)cout<<i<<":"<<dbtest(i)<<endl; return0;}stringdbtest(inta){ return(a%2>0)?"奇数":"偶数";}频繁调用dbtest(),造成栈空间不足和时间浪费27/9927五、内联函数在c++中,为了处理一些频繁调用小函数大量消耗栈空间或者是叫栈内存问题,尤其引入了inline修饰符,表示为内联函数。当编译器发觉某段代码在调用一个内联函数时,它不是去调用该函数,而是将该函数代码,整段插入到当前位置。inlinestringdbtest(inta);//函数申明为内联intmain(void){ for(inti=1;i<10;i++)cout<<i<<":"<<dbtest(i)<<endl; return0;}stringdbtest(inta){ return(a%2>0)?"奇数":"偶数";}28/9928缺点:因为每当代码调用到内联函数,就需要在调用处直接插入一段该函数代码,所以程序体积将增大优点:省去了调用过程,加紧程序运行速度规则1、含有递归调用函数不能设置为inline;规则2、使用了复杂流程控制语句:循环语句和switch语句,无法设置为inline;规则3、因为inline增加体积特征,所以提议inline函数内代码应很短小。最好不超出5行。规则4、inline仅做为一个“请求”,特定情况下,编译器将不理会inline关键字,而强制让函数成为普通函数。出现这种情况,编译器会给出警告消息。规则5、在你调用一个内联函数之前,这个函数一定要在之前已定义为inline,假如在前面申明为普通函数,而在调用代码后面才定义为一个inline函数,程序能够经过编译,但该函数没有实现inline。29/99294.3参数传递一、参数传递方式主调函数与被调函数数据交换:由参数传递与返回值实现按值调用:单项参数传递
按引用调用:双向参数传递intmax(intx,inty){intz;z=x>y?x:y;return(z);}voidmain(void){inta,b,c;cin>>a>>b;
c=max(a,b);cout<<c;}23abXy23z3二、按值调用(传值,按拷贝调用)单向,实际参数->形式参数,传递是参数值30/9930intmain(){intx=2,y=3;inttemp;temp=x;x=y;y=temp;cout<<“x=”<<x<<“,y=”<<y<<endl;}voidswap(intp,intq){inttemp=p;p=q;q=temp;}swap(x,y);传值方式向函数传递参数时,先将实参赋值给形参,然后在被调函数内对形参进行操作。被调函数形参任何改变都不会引发定义于调用函数中实参改变。31/9931函数缺省参数(默认值)比如我们为卖萝卜大娘写一个计价函数。这个函数需要三个参数:用户交多钱?买多少斤萝卜?及萝卜单价。返回值则是大娘应该找多少钱。floatGiveChange(floatmoney,floatcount,floatprice){
returnmoney-count*price;//找钱=已付款-数量*单价}假如萝卜价钱是一个比较稳定数--会变,但极少变。floatGiveChage(floatmoney,floatcount,floatprice=1.0){
returnmoney-count*price;}32/9932缺省行参必须从右边开始定义
intfunc(inta,floatb,intc=0);若在函数调用时指定了形式参数对应实际参数,则形式参数使用实际参数值,不然未指定对应实际参数则形式参数使用缺省值。C++语言允许在函数原型或函数定义中为形式参数指定缺省值,含有缺省值形式参数称缺省形参33/9933voidfun(inta=1,intb=2,intc=3);voidfun(inta,intb,intc=3);注意:赋予缺省值参数必须放在形参表列中最右端。voidfun(inta=1,intb,intc=3);voidfun(inta=1,intb=2,intc=3){cout<<"a="<<a<<",b="<<b<<",c="<<c<<endl;}voidmain(){fun();fun(4);fun(4,5);fun(4,5,6);}运行结果以下:a=1,b=2,c=3a=4,b=2,c=3a=4,b=5,c=3a=4,b=5,c=6
34/99344.4作用域与生存期
在讨论函数形参变量时曾经提到,形参变量只在被调用期间才分配内存单元,调用结束马上释放。这一点表明:形参变量只有在函数内才是有效,离开该函数就不能再使用了。这种变量在空间上有效范围称变量作用域。不但对于形参变量,全部量都有自己作用域。形参变量只有在函数调用期间才存在,其它时间不存在,这种变量在时间上有效性,就是变量生存期。35/9935生存期:(从时间角度考虑)
变量生存期是指在程序运行过程中变量占存放空间时限作用域:(从空间角度考虑)
指在变量占用存放空间时间内变量名字能被引用区域,即变量名作用有效范围。变量说明方式不一样,其作用域也不一样。C++语言中变量,按作用域范围可分为两种,即局部变量和全局变量。36/99364.5全局变量和局部变量(作用域)(1)局部变量---内部变量定义:在函数内定义,只在本函数内有效,在此函数 之外是不能使用这些变量,这称为“局部变量”说明:
主函数main中定义变量也是局部变量;
不一样函数中能够使用相同名字变量,占不一样内 存放单元;
形式参数也是局部变量;
在一个函数内部,能够在复合语句中定义变量,这 些变量只在本复合语句中有效
37/9937/*函数f1*/intf1(inta){intb,c;……}/*函数f2*/intf2(intx){inty,z;……}main(){intm,n;……}a,b,c作用域:仅限于函数f1()中x,y,z作用域:仅限于函数f2()中m,n作用域:仅限于main函数中例子38/9938不一样函数中同名变量#include<iostream.h>#include<conio.h>voidsub(){inta,b;a=6;b=7;cout<<a<<""<<b<<endl;}intmain(){inta,b;a=3;b=4;voidsub();cout<<a<<""<<b<<endl;sub();cout<<a<<""<<b<<endl;getch();return0;}39/9939intmain(){ intx=2,y=3; { inttemp; temp=x; x=y; y=temp; } cout<<“x=”<<x<<“,y=”<<y<<endl; return0;}复合语句中变量40/9940(2)全局变量---外部变量定义:在函数外部定义变量。
应尽可能少使用全局变量,因为:全局变量在程序全部执行过程中占用存放单元降低了函数通用性、可靠性,可移植性降低程序清楚性,轻易犯错关联性太强,使函数本身独立性太弱不属于哪一个函数,它属于一个源程序文件全局变量能够为本文件中其它函数所共用其有效范围是从定义变量位置开始到根源文件结束说明:41/9941inta,b;/*外部变量*/voidf1()/*函数f1*/{……}floatx,y;/*外部变量*/intf2()/*函数f2*/{……}main()/*主函数*/{……}x,y作用域a,b作用域从上例能够看出:a、b、x、y都是在函数外部定义外部变量,都是全局变量。但x,y定义在函数f1之后,所以它们在f1内无效。a,b定义在源程序最前面,所以在f1,f2及main内不加说明也可使用。42/9942输入长方体长宽高l,w,h。求体积及三个面x*y,x*z,y*z面积。ints1,s2,s3;intvs(inta,intb,intc){intv;v=a*b*c;s1=a*b;s2=b*c;s3=a*c;returnv;}intmain(){intv,l,w,h;cout<<"inputlength,widthandheight:";cin>>l>>w>>h;v=vs(l,w,h);cout<<v<<'\n'<<s1<<'\n'<<s2<<'\n'<<s3<<'\n';return0;}程序说明:本程序中定义了三个外部变量s1,s2,s3,用来存放三个面积,其作用域为整个程序。因为语言要求函数返回值只有一个,当需要增加函数返回数据时,用外部变量是一个很好方式。本例中,如不使用外部变量,在主函数中就不可能取得v,s1,s2,s3四个值.而采取了外部变量,在函数vs中求得s1,
s2,s3值在main中依然有效。因另外部变量是实现函数之间数据通讯有效伎俩。43/9943inta=3,b=5;max(inta,intb){intc;c=a>b?a:b;return(c);}intmain(){inta=8;cout<<"max="<<max(a,b)<<'\n';Return0;}全局变量与局部变量同名,在局部时,局部变量起作用运行结果:max=844/9944函数与函数之间通信方式:参数传递与返回值全局变量int
a=3;
int
main()
{
int
a=5;
cout<<"loacal:a="<<a<<endl;
cout<<"global:a="<<::a<<endl;
return
0;
}作用域运算符45/9945全局变量副作用voidprt();inti;intmain(){for(i=0;i<5;i++)prt();return0;}voidprt(){for(i=0;i<5;i++)
cout<<'*'<<'\n';printf(“\n”);}运行结果:*****不是25个*没有同名局部变量时,全局变量起作用46/9946程序内存分区程序运行时,从操作系统分一块内存数据区代码区堆区栈区程序一样长生存期程序自动完成份配与释放数据大小固定程序员初始化或自动初始化生存期由程序员决定数据大小固定或不固定程序员初始化程序决定生存期数据大小固定程序员初始化程序区静态存放区动态存放区47/99474.6变量存放类型除作用域(可见性)外另外两个特征:变量存放在计算机何处,变量何时存在—
存放方式变量存在位置:RAM或CPU存放器RAM划分:代码区、静态存放区、动态存放区存放类别:RAM:static、auto,CPU:register48/9948从生存期(时间)来分,变量有两种存放方式静态存放方式:在程序运行期间占用固定存放空间动态存放方式:运行时,依据需要动态分配存放空间代码区静态存放区动态存放区全局变量、局部静态变量形参变量局部动态变量(autoregister)函数调用现场保护和返回地址等49/9949介绍:auto、
register、static
auto变量
:格式:[auto]类型变量名列表;
auto可省略autointa;等价于inta;自动存放类型,只能修饰变量.局部变量,缺省“存放类型”就是auto.自动变量用最多,不会永久占用内存空间50/9950函数内部“auto”能够省略,不写“auto”则隐含确定为自动存放类型.所以,普通所定义无存放类型变量均属自动变量.因为自动变量是局部变量,所以,自动变量只能定义在函数内,其作用域仅限于定义该变量个体内。因为自动变量是动态变量,所以自动变量存放在动态存放区“栈”
。只有在使用它,即定义该变量函数被调用时才给它分配存放单元,开始它生存期。函数调用结束,释放存放单元,结束生存期,系统收回这种变量所占用存放空间。所以函数调用结束之后,自动变量值不能保留。对于自动变量,若没有明确地赋初值时,其初值是不确定。因为自动变量作用域和生存期都局限于定义它个体内(函数或复合语句内),所以不一样个体中允许使用同名变量而不会混同。auto说明:51/9951intmain(){intx=1;voidprt(void);
{
intx=3;prt();cout<<“2nd”<<x<<‘\n’;
}
cout<<“1st”<<x<<‘\n’;return0;}voidprt(void){intx=5;
cout<<“3th”<<x<<‘\n’;}运行结果:x=1作用域x=1作用域x=3作用域x=5作用域3th52nd31st1ptr.cpp52/9952
register变量存放器变量:自动存放类型,只能修饰变量,属于动态局部变量.格式:register类型变量名列表;存放器变量存在于CPU内部存放器中,数量极少,因为CPU中存放器存取速度要比存放器快得多,所以使用存放器变量主要目标是提升程序运行速度.,普通是将循环使用很屡次变量放在存放器中。registerinta,b=3;53/9953只有整型变量能放在存放器中,包含:int、char、short、long等。存放器变量必须是auto类型局部变量、形参,不能是全局变量或静态变量。因为存放器数量极少,不能确保定义存放器变量总是能分配到存放器,当CPU中存放器放不下时,存放器变量自动转变为自动变量存放动态存放区.
对于存放器变量,不能做取地址(&)运算。register说明:54/9954intmain(){ intx=5,y=10; for(intk=1;k<=2;k++) {registerintm=0,n=0;//A m=m+1; n=n+x+y; cout<<"m="<<m<<'\t'<<"n="<<n<<endl; }//B return0;}register.cpp55/9955intfac(intn){
registerinti,f=1;for(i=1;i<=n;i++)f=f*i;return(f);}voidmain(){
inti;for(i=1;i<=5;i++)cout<<i<<"="<<fac(i)<<endl;}只有局部自动变量和形式参数能够作为存放器变量不能定义任意多个存放器变量局部静态变量不能定义为存放器变量fac.cpp56/9956说明变量称为静态变量,静态变量说明格式为:static类型变量名列表;staticinta;依据静态变量定义在函数内还是函数外,可分为局部静态变量与全局静态变量。
static变量57/9957程序开始执行时,为静态局部变量分配存放空间,当调用定义该变量函数结束后,系统并不收回这些变量所占用存放空间,当再次调用函数时,变量仍使用相同存放空间,所以这些变量仍保留原来值,即在整个程序运行期间变量都存在静态局部变量存放在内存静态存放区中。静态局部变量含有确定值,其默认初值为0。即使静态局部变量在函数调用后依然存在,但其它函数不能引用它,只能由定义它函数引用。定义在函数内静态变量称为局部静态变量1)局部静态变量:58/9958形参不能是定义成static。内部变量定义成static后,作用域不变,但生存期变长,在整个程序执行前就存在,直到程序结束才去除掉,其生存期为整个程序运行期。static说明:静态变量值含有“记忆”性。尽管生存期变长,但作用域(可见性)依然局限在定义它局部范围内。59/9959voidf(intx,inty){ intm=0;//定义自动变量m staticintn=0;//定义静态局部变量n m=m+x+y;//自动变量求三个整数和
n=n+x+y;//静态局部变量求三个整数和
cout<<"m="<<m<<'\t'<<"n="<<n<<endl;}intmain(){ inti=5,j=10,k; for(k=1;k<=3;k++) f(i,j); system("pause"); return0;}执行程序后,其输出结果为:m=15n=15m=15n=30m=15n=45静态局部变量用于:要保留函数运行结果,方便下次调用函数时,能继续使用上次计算结果。注意,因为静态变量在程序开始执行直到程序结束一直占用内存空间,当静态变量较多时会占用大量内存空间,所以,没有必要时,普通不主张使用静态局部变量。static.cpp60/9960voidmain(){inti;for(i=0;i<3;i++)
inc1();for(i=0;i<3;i++)
inc2();}voidinc1(){intx=0;x++;
cout<<"ininc1"<<x<<'\n';}voidinc2(){staticintx=0;x++;
cout<<"ininc2"<<x<<'\n';}运行结果:ininc1x=1ininc1x=1ininc1x=1ininc2x=1ininc2x=2ininc2x=3静态内部变量生存期61/99612)全局静态变量:静态全局变量定义中“static”能够省略,不写“static”则隐含确定为静态存放类型。静态全局变量可被作用域内全部函数引用。即可被程序内定义在静态全局变量后全部函数引用。用static说明静态全局变量只能被本文件使用,而不能被其它文件引用。生存期:整个程序运行期间62/9962staticinta=3,b=5;intmax(inta,intb){intc;c=a>b?a:b;return(c);}intmain(){
inta=8;cout<<"max“<<max(a,b));return0;}全局静态变量与局部变量(同名局部变量屏蔽外部变量)运行结果:max=863/9963
extern申明外部类型,仅申明本文件外变量或函数,而不是定义外部变量或函数------外部变量说明
格式:用
extern申明外部变量:extern数据类型
变量表;externinta,b;定义:在函数外定义,可为本文件全部函数共用作用域:从定义变量位置开始到根源文件结束,及有extern说明其它源文件生存期:整个程序运行期间64/9964#include<iostream.h>staticinta=6,b=5;intmax(intx,inty){cout<<a<<‘\t’<<b<<endl; returnx>y?x:y;}intmain(){ intc; c=max(a,b); cout<<"max="<<c<<endl; return0;}程序执行后输出:65max=6对静态全局变量定义在引用之后,需进行引用性说明,其方法是用关键词extern将静态全局变量说明成外部类型变量。65/9965外部变量定义与外部变量说明(申明)不一样staticinta=6,b=5;//定义静态全局变量a,bintmain(int){intc;c=max(a,b);//在主函数中使用静态全局变量a,bcout<<"max="<<c<<endl;return0;}#include<iostream.h>externinta,b;//将静态全局变量a,
b说明成外部变量intmax(intx,inty){cout<<a<<'\t'<<b<<endl;//在函数max()中使用静态全局变量a,breturnx>y?x:y;}在同一文件中定义全局变量,若定义在后引用在前,则引用前要将此全局变量说明成外部变量66/9966在多个文件程序中使用extern说明外部变量当由多个文件组成一个完整程序时,在一个文件中定义全局变量,要被其它文件引用时,引用文件中要用extern将此全局变量说明成外部变量,这么就可在引用文件说明处起,正当地使用该全局变量。即将一个文件中定义全局变量作用域扩展到了引用文件中。/*文件名:exemple5_21.cpp*/#include<iostream.h>externinta,b;//说明ab为外部变量,即对ab进行引用性说明externintmax(intx,inty);//说明max()为外部函数,即对函数进行引用性说明voidmain(void){intc;c=max(a,b);cout<<"max="<<c<<endl;}/*文件名:exemple5_211.cpp*/intmax(intx,inty){returnx>y?x:y;}inta=100,b=7;//定义静态全局变量a、b67/9967intp=1,q=5;floatf1(inta){intb,c;…….}intf3(){…..}charc1,c2;charf2(intx,inty){inti,j;……}main(){intm,n;…….}c1,c2原来作用范围p,q作用范围externcharc1,c2;externcharc1,c2;c1,c2作用范围扩展后c1,c2作用范围扩展后用extern
申明外部变量能够扩展外部变量作用域68/9968intadd(intx,inty){
intz;z=x+y;returnz;}intmain(){
externinta,b;cout<<“a+b=“<<add(a,b);reutrn0;}inta=3,b=4;例用extern扩展外部变量作用域运行结果:a+b=769/9969例用extern将变量作用域扩展到其它文件中intx=10,y=10;externvoidsub();voidadd(void){inty=5;y=10+x;x*=2;cout<<"add:y=“<<y;}voidmain(){x+=5;add();sub();cout<<"main:x=<<x<<“;”<<“main:y=“<<y<<endl;}externintx;voidsub(){inty=5;x-=y;cout<<“;sub:y=“<<y<<endl;}运行结果:add:y=25;sub:y=5;main:x=25;main:y=10;70/9970staticintx=10;voidadd2(){externinty;x+=10;y+=2;cout<<"inadd2x="<<x<<endl;}static型外部变量作用域受到限制,限制在本文件内使用运行结果:inadd1x=4inadd2x=20inadd1x=6inadd2x=30x=6,y=13staticintx=2;inty=3;externvoidadd2();voidadd1();voidmain(){add1();add2();add1();add2();cout<<"x="<x<<<",y="<<y;}voidadd1(){x+=2;y+=3;cout<<"inadd1x"<<x<<endl;}71/9971例文件file1.cinta;voidmain(){…….…….f2;…….f1;…….}f1(){autointb;………f2;……..}f2(){staticintc;………}c作用域b作用域a作用域mainf2f1mainf1f2maina生存期:b生存期:c生存期:72/9972存放类型:auto―――自动(动态,局部变量默认)static―――静态(能够全局,也可局部变量)register――存放器(形参,局部变量,数量有限,整型)
局部变量:全局寿命和局部可见性,继承性extern――外部全局变量,可扩展外部变量作用域用作定义仅作说明静态动态存放方式程序整个运行期间函数调用开始至结束生存期编译时赋初值,只赋一次每次函数调用时赋初值自动赋初值0或空字符不确定未赋初值静态存放区动态区存放区存放器局部变量外部变量作用域定义变量函数或复合语句内本文件其它文件register局部staticauto外部static外部存放类别73/99734.7递归程序设计在函数定义中,一个函数直接或间接地调用自己,称递归调用,这类函数为递归函数。递归就象我们讲那个故事:山上有座庙,庙里有个老和尚,老和尚在讲故事,它讲故事是:山上有座庙,庙里有个老和尚,老和尚在讲故事……递归直接或间接地调用了其本身74/9974这个函数是一个递归函数.不过运行该函数将无休止地调用其本身,这当然是不正确.为了预防递归调用无终止地进行,必须在函数内有终止递归调用伎俩.惯用方法是加条件判断,满足某种条件后就不再作递归调用,然后逐层返回.函数f调用f函数直接调用intf(intx){inty,z;…z=f(y);returnz;}75/9975函数f1调用f2函数函数f2调用f1函数间接调用intf1(intx){inty,z;...z=f2(y);...return(2*z);}intf2(intt){inta,c;...c=f1(a);...return(2*z);}自已调用自已,当然就是一个循环,且假如不辅于前面所学if...语句来控制什么时候能够继续调用本身,什么时候必须结束,那么这个循环就一定是一个死循环在递归循环里,函数之间调用都是系统实现,所以要想“打断”这个循环,我们只有一处“要害”能够下手:在调用会引发递归函数之前,做一个条件分支判断,假如条件不成立,则不调用该函数。76/9976递归调用条件:在有限次调用之后结束递归调用,即:递归必须有一个出口。一个合理递归函数,一定是一个逻辑上类似于这么函数定义:voidF(){
……
if(……)//先判断某个条件是否成立
{
F();
//然后才调用本身
}
……}主要是要知道:什么时候该打断它循环?什么时候让它继续循环?大多数递归函数,最终依靠参数改变来决定是否继续.我们必要彻底明了参数在递归调用过程中怎样改变一个合理递归:77/9977参数在递归调用过程中改变voidF(inta){
F(a+1);}在函数体内调用本身时,我们传给它当前参数加1值,作为新参数假设我们在代码中以1为初始参数,第一次调用F():F(1);F()被第1次调用后,马上就调用了本身,这时参数是a+1,所以新参数值应为2.伴随F函数第二次调用,新参数值也被入栈:再往下模拟过程一致.第三次调用F()时,参数变成3,依然被压入栈,然后是第四次……递归背后循环在一次次地继续,而参数a则在一遍遍循环中不停改变.因为本函数依然没有做结束递归调用判断,所以最终最终:栈溢出78/9978voidF(inta){
if(a<10)F(a+1);}安全递归调用递归在没有控制条件情况下是无穷递归。只有经过控制条件,使递归调用终止,才能应用。上面递归调用都是无终止本身调用。显然,程序中不应该出现这种无终止递归调用,而只能出现有限次数、有终止递归调用,这能够用if语句来控制,只有在某一条件成立时才继续执行递归调用,不然就不再继续。
递归调用条件:在有限次调用之后结束递归调用,即:递归必须有一个出口。79/9979递归函数返回-----递归函数返回次序
函数递归调用,和穿衣脱衣类似,不过内外相反而已。开始调用时,它是外层调内层,内层调更内一层。等到最内层因为条件不允许,必须结束了.最内层结束了,它就会回到稍外一层,稍外一层再结束时,退到再稍外一层,层层退出,直到最外层结束。80/9980n!=1n=0或n=1n(n-1)!n>1f(n)=1n=0或n=1nf(n-1)n>1用递归法计算n!。f(4)4*f(3)3*f(2)2*f(1)2*13*2*14*3*2*1递推回归81/9981用递归法计算n!。longf(intn){longr;if(n>1)r=f(n-1)*n;elser=1;return(r);}voidmain(){intn;longy;cout<<"inputainteagernumber:";cin>>n;y=f(n);cout<<y<<endl;}
程序说明:
程序中给出函数f是一个递归函数.主函数调用f后即进入函数f执行,假如n<0,n==0或n=1时都将结束函数执行,不然就递归调用f函数本身.因为每次递归调用实参为n-1,即把n-1值赋予形参n,最终当n-1值为1时再作递归调用,形参n值也为1,将使递归终止.然后可逐层退回。82/9982递归问题:有5个人坐在一起。第5个人多少岁?他说比第4个人大2岁第4个人多少岁?他说比第3个人大2岁第3个人多少岁?他说比第2个人大2岁第2个人多少岁?他说比第1个人大2岁第1个人多少岁?他说是10。请问第5个人多大?#include<iostream.h>intage(intn){intc; if(n==1)c=10; elsec=age(n-1)+2; returnc;}voidmain(){ cout<<age(5)<<endl;}age(5)=age(4)+2age(3)=age(2)+2age(4)=age(3)+2age(2)=age(1)+2age(1)=10age(2)=age(1)+2=12age(3)=age(2)+2=14age(4)=age(3)+2=16age(5)=age(4)+2=18即age(n)=10 (n=1)age(n)=age(n-1)+2 (n>1)83/9983递归一个非常奇妙和美妙算法形式,奇妙美妙背后是比较难了解。但用起来却异常简练。小猴第一天摘下若干枣子,当即吃掉了二分之一,不过瘾又多吃了一个;第二天吃了剩下二分之一又多吃了一个;以后每一天都吃了前一天剩下二分之一多一个。到第十天小猴再想吃时,见到只剩下一只枣子了。问第一天这堆枣子有多少?从上题中我们可看到一个令人欣喜规律,第十天为1,第九到第一天中后一天与1和两倍与前一天相等。下面就对这一规律做了描述:intmonkey(intx){ intjujube;if(x==10) jujube=1; else jujube=2*(monkey(x+1)+1);}84/9984Hanoi(汉诺塔问题)一个古典数学问题:古代有一个梵塔,塔内有3个座A、B、C,开始时A座上有64个盘子,盘子大小不等,大在下,小在上。有一个老和尚想把这64个盘子从A座移动到C座,每次只允许移动一个盘,且在移动过程中,在每个座上都一直保持大盘在下,小盘在上。在移动过程中能够利用B座,写出移动步骤。这是一个只有用递归方法才能处理问题。A B C85/9985分析3个盘子情况:1.将A座上2个盘子移到B座(借助C);2.将A座上1个盘子移到C座;3.将B座上2个盘子移到C座(借助A)。其中第2步能够直接实现。第1、3步还需要递归分解。A B CA B CA B C86/9986递归分解:第1步——将A座上2个盘子移到B座(借助C),分解为:1.1将A上一个盘子从A移到C;1.2将A上一个盘子从A移到B;1.3将C上一个盘子从C移到B。A B C1.1A B C1.2A B C1.3A B C3.第3步——将B座上2个盘子移到C座(借助A),分解为:3.1将B上一个盘子从B移到A;3.2将B上一个盘子从B移到C;3.3将A上一个盘子从A移到C。将以上综合起来,可得到移动3个盘子步骤为:A→C,A→B,C→B,A→C,B→A,B→C,A→C。共经历7(=23-1)步。能够推知,移动n个盘子需要经历2n-1。87/99871.将A座上n-1个盘子借助C座移到B座上;2.将A座上剩下1个盘子移到C座上;3.将B座上n-1个盘子借助A座移到C座上。 将第1步和第3步表示为:将“one”座上n-1个盘子借助“two”座移到“three”座。只是在第1步和第3步中,one、two、three和A、B、C对应关系不一样。对第1步,对用关系是:one——A,two——C,three——B。对第3步,对用关系是:one——B,two——A,three——C。所以,能够将上面3个步骤分成两类操作:⑴将n-1个盘子从一个座移到另一个座上(n>1);⑵将1个盘子从一个座移到另一个座上; 分别用两个函数来实现这两类操作。hanoi(n,one,two,three)
表示“将n个盘子从one座借助two
座移到three座,函数move(x,y)
表示将一个盘子从x座移到y座。one、two、three、x和y对应不一样情况A、B、C。将n个盘子从A座移到C座,能够分解为3个步骤:88/9988汉诺塔程序:voidmove(charx,chary){cout<<x<<y;
}voidhanoi(intn,charone,chartwo,charthree){if(n==1) move(one,three);else {hanoi(n-
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 交通行业智能交通管控方案
- 钢筋购买销售合同
- 卫星通信系统建设工程承包合同
- 劳动合同和人力资源公司签订
- 光伏安装劳务分包合同
- 装饰装修工人劳务合同
- ERP软件购销合同
- 人力资源派遣服务协议
- 第5课《设计汽车标志》(教学设计)长春版三年级下册综合实践活动
- Module 9 Unit 2 I want to go to Shanghai(教学设计)-2024-2025学年外研版(三起)英语六年级上册
- 《社区康复》课件-第八章 视力障碍患者的社区康复实践
- 透析患者的血糖管理
- 汉堡王行业分析
- 人教版数学三年级下册全册双减同步分层作业设计 (含答案)
- 肝硬化“一病一品”
- 2024大型活动标准化执行手册
- 大学美育十六讲六七讲
- 沥青拌合站讲义课件
- 《快递实务》 教案 项目三 快递收件业务操作、项目七 快递保价与赔偿业务
- 《逆向建模与产品创新设计》课程标准
- AI时代的艺术创作与表达
评论
0/150
提交评论