第05章-问题求解模块化_第1页
第05章-问题求解模块化_第2页
第05章-问题求解模块化_第3页
第05章-问题求解模块化_第4页
第05章-问题求解模块化_第5页
已阅读5页,还剩118页未读 继续免费阅读

下载本文档

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

文档简介

第05章_问题求解模块化第一页,共123页。内容提要5.1模块化程序设计5.2函数的概念5.3函数调用和参数传递5.4函数的特殊调用形式5.5内联函数5.6函数重载5.7程序设计实例2第二页,共123页。5.1模块化程序设计模块化程序规模较大的程序可以按功能划分成若干个相对独立的模块每个模块功能由一个函数实现通过函数调用将这些函数组织在一起C++程序的执行从main()函数开始;在main()中调用其它的函数;其它函数执行后返回到main(),最后在main()中结束运行第三页,共123页。函数之间的调用关系示意图main函数调用了f1()、f2()、f3()这3个函数函数f1()调用了函数f3()函数f2()调用了函数f4()第四页,共123页。C++程序框架通常由3个部分组成(1)第1部分:对每一个将被调用的函数进行声明voidf1();voidf2();voidf3();voidf4();(2)第2部分:定义main()函数voidmain(){……f1();//调用函数f1f2();//调用函数f2f3();//调用函数f3……}第五页,共123页。(3)第3部分:定义其它的各个函数。voidf1()//定义函数f1{……f3();//调用函数f3}voidf2()//定义函数f2{……f4();//调用函数f4……}voidf3()//定义函数f3{……}第六页,共123页。库函数和自定义函数(1)库函数在函数库中已定义的函数,也称为标准函数,分布在不同的函数库中,例如iostream、cmath和string等。使用库函数时,在程序开头将该函数所在的函数库进行包含包含格式:#include“函数库名”例如:#include<iostream>#include<cmath>usingnamespacestd;(2)自定义函数:由用户自行编写第七页,共123页。【例5-1】计算圆的面积定义两个函数,根据半径计算圆的面积和周长。在主函数中,输入一个圆的半径值,然后对输入的半径值进行判断,当该值大于零时,调用函数计算这个圆的面积和周长,并输出计算的结果;否则显示“输入错误”的信息。第八页,共123页。【源程序】#include<iostream>usingnamespacestd;doublearea(doubler);//声明计算面积的函数area()doublelen(doubler); //声明计算周长的函数len()voidmain(){ doubler; //定义变量r保存圆的半径

cout<<"请输入圆的半径:"; cin>>r;第九页,共123页。 if(r>0) {cout<<"面积="<<area(r)<<endl; //调用函数area()计算面积

cout<<"周长="<<len(r)<<endl; //调用函数len()计算周长

} else cout<<"输入错误"<<endl;}第十页,共123页。doublearea(doubler) //定义计算面积的函数area{ return3.1416*r*r;//计算并返回圆的面积}doublelen(doubler)//定义计算周长的函数len{ return2*3.1416*r;//计算并返回圆的周长}第十一页,共123页。5.2函数的概念函数的定义方式返回值的概念函数的声明第十二页,共123页。5.2.1函数的定义1.函数定义的一般形式类型名函数名(类型名形参1,类型名形参2,…)

{函数体

}(1)类型名:函数返回值的类型(2)函数名:函数名的命名要符合标识符命名的规则。(3)形参的类型和名称:形参用来在函数调用时接收从主调函数那里传递过来的数据。(4)函数体:用来实现该函数的功能。第十三页,共123页。2.几种特殊形式的函数(1)无参函数没有形参的函数称为无参函数,圆括号不能省略。(2)空函数如果函数体为空,该函数称为空函数,空函数也可以被调用,调用后也可以返回到主调函数。空函数通常用在程序设计的最初阶段,目的是保证整个程序的完整性,以后再向函数体中填写具体语句第十四页,共123页。3.Void类型的函数用关键字void定义无类型或称为空类型的函数,明确表示不带回值。例如:voidfun(){cout<<”Hello”;}该函数仅完成输出一个字符串,不需要返回值第十五页,共123页。根据参数及返回值的函数分类(1)带参数并且有返回值函数类型函数名(形参表列){函数体}(2)不带参数但有返回值函数类型函数名(){函数体}(3)带参数但没有返回值void函数名(形参表列){函数体}(4)不带参数也没有返回值void函数名(){函数体}第十六页,共123页。5.2.2函数的返回1.return语句作用是返回到主调函数,如果函数体中没有该语句,则遇见函数体的右花括号时返回格式1:return;用于函数类型为void,返回时没有返回值。格式2:return<表达式>;先计算表达式,然后将结果返回给主调函数,只能带回一个值例如:intmax(intx,inty){if(x>y)returnx;elsereturny;}第十七页,共123页。2.返回值的类型与函数类型不一致的情况返回值的类型在定义函数时指定,如果return语句中表达式的类型与函数定义时的类型不一致,返回时以函数类型为准,这时系统会对return语句中表达式的值自动进行类型转换。第十八页,共123页。【例5-2】返回值与函数类型不一致定义求两个float型数的最大值的函数,函数的返回类型是int,return语句的表达式结果类型为float,观察主函数中的计算结果。第十九页,共123页。【源程序】#include<iostream>usingnamespacestd;intmax(floatx,floaty){return(x>y?x:y);}voidmain(){floata,b;intc;cin>>a>>b;c=max(a,b);cout<<"Max="<<c;}第二十页,共123页。【程序分析】函数max的类型是int,return语句中表达式值的类型是float,二者不一致,先将x>y?x:y的结果转换为int,然后再返回给main。第二十一页,共123页。5.2.3函数的声明1.函数调用的原则调用任何函数之前,应该先对该函数进行声明如果被调函数出现在主调函数之前,这时,定义函数的同时也对该函数进行了声明,可以省略对该函数的声明如果被调函数出现在主调函数之后,就要在函数调用之前对该函数进行声明。第二十二页,共123页。示例:被调函数在主调函数之前定义#include<iostream>usingnamespacestd;floatf(){return3.5;}voidmain(){cout<<f();}该程序可以正常的运行。第二十三页,共123页。出错的程序:交换两个函数的顺序#include<iostream>usingnamespacestd;voidmain(){cout<<f();}floatf(){return3.5;}编译时会出错,原因是未对函数进行声明。第二十四页,共123页。2.函数的声明和函数的原型声明格式1:类型名函数名(类型名形参1,类型名形参2,…);声明格式2:类型名函数名(类型名,类型名,…);声明格式称为函数原型,由函数头部加上分号组成例如:以下是函数max的定义:intmax(intx,inty){return(x>y?x:y);}该函数的函数原型是:intmax(intx,inty);或intmax(int,int);第二十五页,共123页。5.3函数调用和参数传递5.3.1函数调用的一般格式1.实参的几种形式函数调用的一般形式:函数名(参数表列)调用函数时,格式中参数表列的各个参数称为实际参数,简称实参,实参向被调函数的形参传递数据。例如:实参是变量: c=max(a,b);实参是常量: c=max(3,4);实参是表达式: c=max(3+5,4+3);实参是另一个函数调用的结果:c=sqrt(max(a,3));实参的个数、类型和次序应与被调函数的形参一一对应第二十六页,共123页。【例5-3】函数调用时实参向形参传递数据编写函数,显示指定的字符n次,n和字符作为参数,函数不需要返回值。在主函数中,以不同的参数调用该函数两次,比较运行结果。第二十七页,共123页。【源程序】#include<iostream>usingnamespacestd;voidprint_char(charc,intn)//两个形参{inti;//定义循环变量for(i=0;i<n;i++)//执行n次的循环cout<<c;//显示字符cout<<endl;//换行}//函数没有返回值,可以省略return语句第二十八页,共123页。voidmain()//主函数{print_char('*',15);//函数调用,括号中为实参,顺序一致,类型一致

print_char('^',10);//函数调用,用另一组实参,第1个字符型,第2个整型}第二十九页,共123页。2.函数调用的几种形式(1)语句调用作为函数调用语句,完成一定的操作,不返回任何值。(2)表达式调用函数调用出现在表达式中,函数值参与表达式的运算例如:c=2*max(a,b);(3)函数的值作为另一个函数调用的参数这时被调函数作为其它函数的参数例如:m=max(a,max(b,c));第三十页,共123页。5.3.2参数的传递方式在C++语言中,函数之间调用时通过参数进行数据传递,从传递内容上看,参数传递有值传递、地址传递和引用传递3种方式第三十一页,共123页。1.值传递将实参的值依次传递给对应的形参,形参变量只有在发生函数调用时才分配内存单元用来接受由实参传过来的数据。实参与形参各占不同的单元,当调用结束后,形参所在内存单元被释放,而实参仍保留原值。第三十二页,共123页。【例5-4】值传递验证在值传递过程中,形参的改变对实参有无影响编写函数,交换两个整型变量的值。在主函数中,使用值传递方式的调用该函数,参数用两个变量,观察调用前后这两个变量的值。第三十三页,共123页。【源程序】值传递的调用方式#include<iostream>usingnamespacestd;voidsx,inty);//swap()函数的声明voidmain(){inta=3,b=4;cout<<"a="<<a<<"b="<<b<<endl; //显示调用前的实参值

s); //函数的值传递调用

cout<<"a="<<a<<"b="<<b<<endl; //显示调用后的实参值}第三十四页,共123页。voidsx,inty)//swap()函数的定义{intz;cout<<"x="<<x<<"y="<<y<<endl; //显示交换前的形参的值z=x;x=y;y=z; //交换两个形参的值cout<<"x="<<x<<"y="<<y<<endl; //显示交换后的形参的值}结论:变量a和b的值并没有交换。第三十五页,共123页。2.引用传递如果形参是引用名,在函数调用时,形参变量与实参变量实际表示的是同一内存单元,在被调函数中对引用变量的操作和在主调函数中使用实参的效果是一样的,这样,可以通过引用变量在被调函数中改变主调函数中变量的值。第三十六页,共123页。【例5-5】引用传递使用引用传递在被调函数中改变实参的值。编写函数,交换两个整型变量的值,形参采用引用传递在主函数中,调用该函数,参数用两个变量,观察调用前后这两个变量的值。第三十七页,共123页。【源程序】引用传递#include<iostream>usingnamespacestd;voids&); //函数swap()的形参是引用名intmain(){inta=5,b=10;//定义并初始化两个变量cout<<"a="<<a<<",b="<<b<<endl;//显示调用前的实参值s); //函数的引用传递调用cout<<"a="<<a<<",b="<<b;//显示调用后的实参值

return1;}第三十八页,共123页。voids&m,int&n)//两个形参都为引用名{intt=m;//交换变量m,n的值m=n;n=t;}第三十九页,共123页。5.3.3设置形参的默认值C++中允许为形参指定默认的值,在函数调用时如果有实参,则形参使用实参的值,如果没有指定与形参对应的实参,形参自动使用默认的值指定参数的默认值可以在函数定义中进行,也可以在函数原型中进行,通常是写在函数名在程序中第一次出现的位置。例如:intadd(intx=0,inty=0);第四十页,共123页。【例5-6】默认参数值的使用编写函数,计算两个数的和并显示,参数的默认值为0,函数无返回值。编写主函数,提供不同的实参调用该函数,观察结果,分析原因。第四十一页,共123页。【源程序】#include<iostream>usingnamespacestd;voidadd(intx=0,inty=0){cout<<x<<"+"<<y<<"="<<x+y<<endl; }intmain(){add(1,2);add();add(3);return1;}第四十二页,共123页。对部分形参定义默认值规定:没有默认值的形参只能出现在形参表列的前边,默认值出现在从右到左的连续若干个形参中。下面定义方法是允许的:

voidfun(inti=1,intj=2,intk=3);voidfun(inti,intj=2,intk=3);voidfun(inti,intj,intk=3);下面定义方法是不允许的:

voidfun(inti=1,intj=2,intk);voidfun(inti=1,intj,intk);voidfun(inti,intj=2,intk);第四十三页,共123页。5.3.4一维数组名作为函数的参数数组名作参数时,主调函数和被调函数的两个数组共占相同的内存单元,这样,如果被调函数中各数组元素值发生变化,在返回主调函数后,实参数组中元素的值也同时变化第四十四页,共123页。【例5-7】数组名作为函数的参数。编写函数,计算数组中第m个元素(从0开始)开始的n个元素之和。第四十五页,共123页。【源程序】#include<iostream>usingnamespacestd;intfun(intb[],intm,intn)//定义求数组元素和的函数,数组作参数,数组大小可以省略{ inti,s=0;//定义循环变量及和的初始值for(i=m;i<m+n;i=i+1)//用循环求和 s=s+b[i];//逐步加数组的元素 returns;//返回指定数组元素的和}第四十六页,共123页。intmain(){intx,a[]={0,1,2,3,4,5,6,7,8,9};x=fun(a,0,10); //调用函数,求第0个元素开始的10个元素的和

cout<<x<<endl; //显示结果

x=fun(a,3,5); //调用函数,求第3个元素开始的5个元素的和

cout<<x<<endl; //显示结果

return1; //主函数结束}第四十七页,共123页。【例5-8】冒泡法排序编写函数,用冒泡法对一组整数进行从小到大的升序排序。对数组中的数据进行排序,就是重新调整每个元素的位置,保证元素的值按下标的顺序依次递增(升序)或依次递减(降序)。第四十八页,共123页。冒泡法算法描述对n个数进行n-1轮的冒泡比较:第一轮将最大的元素沉到最底部,即放到数组的最后一个位置;第二轮将剩余的n-1个数中的最大数即n个数中的次最大值下沉;依此类推,每一轮都将剩余的数中的最大数下沉;当进行n-1轮之后,最大的n-1个沉下去,最上面自然就是最小的数,整个排序就此完成第四十九页,共123页。【源程序】#include<iostream>usingnamespacestd;voidsort(intb[],intn)//冒泡法排序的函数{ inti,j,t; for(j=0;j<n-1;j++)//外循环控制比较轮次为个数减1 for(i=0;i<n-j;i++)//内循环控制每一轮的比较次数

if(b[i]>b[i+1])//相邻两个进行比较第五十页,共123页。

{ t=b[i];b[i]=b[i+1];b[i+1]=t;}//交换两个数的位置

}voidprint(intb[],intn)//该函数顺序显示输出数组元素{ inti; for(i=0;i<n;i++)cout<<b[i]<<""; cout<<endl;}第五十一页,共123页。intmain(){ inta[10]={9,4,8,12,65,-76,1,0,100,-45};//定义并初始化一维数组

cout<<"排序前:";print(a,10);//调用print函数显示排序前数组元素

sort(a,10);//调用sort函数对数组元素进行排序

cout<<"排序后:"; print(a,10);//调用print函数显示排序后数组元素

return1;}第五十二页,共123页。5.4函数的特殊调用形式嵌套调用递归调用第五十三页,共123页。5.5.1嵌套调用在一个函数的调用过程中,被调函数又调用了另一个函数。C++中可以嵌套调用,但是不可以嵌套定义函数。第五十四页,共123页。【例5-9】函数的嵌套调用函数square()计算一个数的平方;另一个函数ssum(),计算两个数的平方和,其中的平方要调用square()函数实现;主函数,调用函数ssum计算用户输入的两个数的平方和。第五十五页,共123页。【源程序】函数的嵌套调用#include<iostream>usingnamespacestd;intsquare(intn) //计算整数的平方{returnn*n;}intssum(intx,inty)//计算两个数的平方和{returnsquare(x)+square(y);//调用计算平方的函数}第五十六页,共123页。intmain(){intm,n;cout<<"Pleaseinputtwointeger:";cin>>m>>n;cout<<m<<"^2+"<<n<<"^2="<<ssum(m,n)<<endl;return1;}第五十七页,共123页。在定义一个函数的过程中直接或间接地调用其自身,有两个阶段(1)递推阶段将原来的问题不断地分解为新的问题,逐渐从未知向已知的方向推测,最终到达已知的条件。(2)回归阶段从已知的条件出发,按递推的逆过程,逐个求值,最后到达递推的开始。5.5.2递归调用第五十八页,共123页。【例5-10】用递归调用计算阶乘n!【问题分析】由于5!=5×4!,4!=4×3!……2!=2×1!,1!=1,这样,可以得到计算阶乘n!的递归公式是:当n=0或1时,n!=1

当n>1时,n!=n×(n-1)!第五十九页,共123页。【源程序】用递归调用计算阶乘#include<iostream>usingnamespacestd;intfac(intn) //定义函数,计算n的阶乘{intf;//f保存n的阶乘

if(n==0||n==1)//n是0或1时值是确定的、已知的

f=1;else//n大于1时,n!=n*(n-1)!=n*fac(n-1)f=fac(n-1)*n;//如果n>1调用自身,即递归调用

returnf;//返回结果}第六十页,共123页。voidmain()//主函数{intn,y;cin>>n;//输入nif(n>0)//n>0时才计算阶乘

{y=fac(n);//调用函数,计算阶乘

cout<<n<<"!="<<y;//显示结果

}else//n<=0的情况

cout<<"n的值应大于0";}第六十一页,共123页。【例5-11】Hanoi塔问题编程显示每次移动一个盘子的具体过程。图5-4中,有几个大小不同的圆盘和三根立柱,每个圆盘按由小到大顺序插在A柱子上,B和C两个柱子上是空的第六十二页,共123页。要求将这几个圆盘按由大到小顺序搬到C柱子上,完成后的外观和现在的A柱子上是一样的,搬动时按下面的规则进行:(1)搬动时可以借助B柱子;(2)每次只能搬动一个圆盘;(3)任何时候不能将大圆盘放在小圆盘之上;(4)圆盘只能在这三根柱子之间搬动。第六十三页,共123页。问题分析:3个步骤操作步骤:(1)将n-1个盘子从A柱移到B座;(2)将A柱上剩下的1个盘子移到C柱;(3)将n-1个盘子从B柱移到C柱。其中的(1)和(3)步并没有直接完成,例如(1)可以用下面的步骤描述:1)将n-2个盘子从A柱移到C座;2)将A柱上剩下的1个盘子移到B柱;3)将n-2个盘子从C柱移到B柱。这里的1)和3)还可以再进一步的描述,直到每一步中盘子个数只有一个时就可以像第(1)步那样直接移动了,显然,这种分析反映了递归思想。第六十四页,共123页。2类操作和2个函数3个步骤可以分成两类操作:(1)n>1时:将n-1个盘从一个柱移到另一个柱上,这是一个递归的过程。(2)n=1时:将1个盘子从一个柱移到另一柱上。第1类操作可以定义下列函数完成:voidhanoi(intn,chara,charb,charc);该函数实现将n个盘子从a柱借助b柱移到c柱,形参a、b、c分别代表三根柱子。第2类操作可以定义下列函数完成:voidmove(charx,chary);该函数实现将1个盘子从x柱移到y柱,形参x、y分别代表三根柱子hanoi函数是一个递归函数,当参数n的值为1时调用move函数,n大于1时进行自身的递归调用。第六十五页,共123页。【源程序】Hanoi塔问题#include<iostream>usingnamespacestd;voidmove(charx,chary)//函数move将一个盘子从x移动到y{ cout<<x<<"---->"<<y<<endl;}第六十六页,共123页。voidhanoi(intn,chara,charb,charc){if(n==1)//n=1时直接调用movemove(a,c);else

{hanoi(n-1,a,c,b);//n>1时调用自身,借助c将n-1个盘子从a移到bmove(a,c);hanoi(n-1,b,a,c);//n>1时调用自身,借助a将n-1个盘子从b移到c}}第六十七页,共123页。intmain(){intm;cout<<"请输入盘子个数:";cin>>m;cout<<"移动"<<m<<"个盘子的过程如下:"<<endl;hanoi(m,'A','B','C'); return1;}第六十八页,共123页。5.5内联函数问题:代码不长又经常被调用的函数,系统为调用所花费的时间和空间开销较大,有时甚至会影响程序的运行效率解决方法:将函数定义为内联函数定义格式:inline函数类型函数名(形参及其类型表列){函数体}程序编译将内联函数调用表达式用内联函数的函数体替代第六十九页,共123页。【例5-12】内联函数的使用。编写函数,计算函数的平方,该函数定义为内联函数。#include<iostream>usingnamespacestd;inlineintsquare(intx)//使用关键字inline表示定义内联函数{ returnx*x; //该函数内只有一条语句}voidmain(){inti,sum=0; for(i=1;i<=10;i++) sum=sum+square(i); cout<<"sum="<<sum;}第七十页,共123页。5.6函数重载函数重载机制两个或两个以上的函数具有相同的函数名,这些函数被称为重载函数,只要这些函数形参的个数不同或形参类型不完全一样,编译系统根据实参和形参的个数或类型的匹配关系,在同名函数中自动选择调用某个函数。第七十一页,共123页。【例5-13】形参个数相同但类型不同的函数重载使用函数重载分别编写求两个整型、双精度型和字符型的最大值的函数。本例中设计3个功能相同的函数,都是求两者中的最大值,只是每个函数形参的类型不同,分别是整型、双精度型和字符型。第七十二页,共123页。源程序#include<iostream>usingnamespacestd;intmax(intx,inty)//求整型数最大值的函数{ returnx>y?x:y;}doublemax(doublex,doubley)//求双精度型数最大值的函数{ returnx>y?x:y;}第七十三页,共123页。charmax(charx,chary)//求字符型数最大值的函数{ returnx>y?x:y;}voidmain(){cout<<max(4,5)<<endl;//实参为整型数

cout<<max(5.6,1.2)<<endl;//实参为双精度型数

cout<<max('x','y')<<endl;//实参为字符型数}第七十四页,共123页。【例5-14】形参个数不同的函数重载使用函数重载,分别编写求两个、三个、四个数的和的函数。设计3个功能相同的函数,都是求形参变量之和并将结果返回到主调函数,3个函数的参数类型一数,但个数不同,分别是2、3、4个。第七十五页,共123页。【源程序】#include<iostream>usingnamespacestd;intadd(intx,inty) //有两个形参{intsum;sum=x+y;returnsum;}intadd(intx,inty,intz)//有3个形参{intsum;sum=x+y+z;returnsum;}intadd(intx,inty,intz,intt)//有4个形参{intsum;sum=x+y+z+t;returnsum;}第七十六页,共123页。voidmain(){inta,b,c;a=add(3,5); //有2个实参b=add(3,5,7); //有3个实参c=add(3,5,7,9); //有4个实参cout<<a<<endl;cout<<b<<endl;cout<<c<<endl;}第七十七页,共123页。5.7C++中的字符串处理函数1.字符串复制函数strcpy格式:strcpy(字符数组名,字符串)作用:将字符串复制到字符数组中字符串可以是字符数组名、字符串常量、指针变量示例:strcpy(str2,str1);strcpy(str1,"Friday");第七十八页,共123页。2.字符串连接函数strcat格式:strcat(字符串1,字符串2)作用:将字符串2连接到字符串1之后第七十九页,共123页。【例5-15】将3个字符串连接成一个#include<iostream>#include<string>usingnamespacestd;intmain(){charstr1[20]={"computer"};//第1个字符串保存在str1中charstr2[]={"room"}; //第2个字符串保存在str2中strcat(str1,"-"); //第1个字符串和"-"连接strcat(str1,str2); //连接后的第1个字符串和第2个连接cout<<str1;return1;}第八十页,共123页。3.字符串比较函数strcmp格式:strcmp(字符串1,字符串2)作用:比较两个字符串的大小并返回一个整数。两个字符串比较过程:两个字符串自左到右逐个字符比较,即先比较两个字符串的第0个字符,如果相等,再比较这两个字符串的第1个字符,……参与比较的是这两个字符对应的ASCII码。比较过程中,遇到对应字符不相等或遇到某个字符串先到结束标志’\0’时,比较结束,如果两个字符串长度相等,并且对应位置上的字符都相同,则比较的结果是两个字符串相等。函数值的规定:(1)如果两个字符串相等,函数值为0;(2)如果字符串1大于字符串2,函数值为1;(3)如果字符串1小于字符串2,函数值为-1。第八十一页,共123页。字符串比较示例一:cout<<strcmp("aaa","aaaa")<<endl; //字符'\0'<'a',结果为-1cout<<strcmp("1a","aa")<<endl; //字符'1'<'a',结果为-1cout<<strcmp("Abc","abc")<<endl; //字符'A'<'a',结果为-1第八十二页,共123页。字符串比较示例二:定义:chara[5]="1234",b[5]="4321";cout<<strcmp(a,"1234")<<endl; //两个字符串相等,结果为0cout<<strcmp(a,"123")<<endl; //字符'4'>'\0',结果为1cout<<strcmp(a,b)<<endl; //字符'1'<'4',结果为-1第八十三页,共123页。5.计算字符串长度函数strlen格式:strlen(字符串)作用:返回字符串长度,即字符串中包含的字符个数。不包括结束标志’\0’。5.字母变小写函数strlwr格式:strlwr(字符串)作用:将字符串中的大写字母转换成小写字母。6.字母变大写函数strupr格式:strupr(字符串)作用:将字符串中的小写字符母转换为大写字母。第八十四页,共123页。5.8变量的作用域和存储类型变量作用域是指变量的作用范围。根据变量的作用范围不同,可以把变量分为局部变量和全局变量。第八十五页,共123页。5.8.1局部变量(1)在一个函数内部定义的变量(2)函数的形参是局部变量。(3)在main中定义的变量是局部变量。(4)在复合语句中定义是局部变量,仅在复合语句的范围内有效。第八十六页,共123页。【例5-16】main和复合语句中的局部变量#include<iostream>usingnamespacestd;voidmain(){inti=1,j=3;//main中定义的局部变量

cout<<i<<",";i++;{inti=0;//复合语句中定义的变量i,与上面的同名

i+=j*2;//这里是复合语句中定义的变量icout<<i<<","<<j<<",";} cout<<i<<","<<j;//这里是main中定义的变量i}第八十七页,共123页。5.8.2全局变量在函数之外、类之外定义的变量,全局变量可以为本源程序中的所有函数、类或复合语句所访问。定义的全局变量如果没有初始化,系统自动将其初始化为0。全局变量和某个局部变量允许同名在局部变量的作用范围内,如果要使用全局变量,应在全局变量前使用作用域运算符::第八十八页,共123页。【例5-17】全局变量和局部变量#include<iostream>usingnamespacestd;inta=3,b=5;//这里定义了两个全局变量intmax(inta,intb)//两个形参是局部变量{returna>b?a:b;//这里使用的是局部变量}voidmain(){inta=8;//该处定义的局部变量与全局变量同名

cout<<max(a,b); //第1个实参是局部变量,第2个是全局变量}第八十九页,共123页。5.8.3变量存储类型

1.C++程序使用的内存区域(1)程序代码区:存放各个函数的代码;(2)全局数据区:存放全局数据和静态数据,该区域的数据一直保持到程序的结束;(3)栈区:存放局部数据,当函数被调用时,为函数中的局部变量分配存储空间,函数调用结束时收回该函数在栈区分配的单元;(4)堆区:存放程序的动态数据。第九十页,共123页。变量的存储类型是指定变量的具体存储区域,在默认情况下,变量存储区域:全局变量保存在全局数据区;局部变量保存在栈区;用new或malloc动态分配的变量保存在堆区;第九十一页,共123页。2.局部变量的存储方式(1)auto类型又称为自动变量,分配在栈区,缺省方式,关键字auto可以省略。(2)register寄存器变量用register将局部变量的值放在寄存器中,用来提高执行效率,使用该类型时应注意:仅局部变量和形参可作为寄存器变量;寄存器数目有限,如果定义了多个寄存器变量,多余的自动作auto型处理;寄存器变量没有地址,因此不能作地址运算第九十二页,共123页。(3)static静态将局部变量分配到全局数据区空间,这样的变量称为静态局部变量,有以下特点:初始值缺省为0;局部变量在函数调用结束后所占的内存单元不释放,其值可以保持到函数的下一次调用。第九十三页,共123页。【例5-18】静态局部变量的使用使用静态局部变量统计某个函数被调用的次数。静态局部变量在函数调用结束后所占的内存单元不释放,其值可以保持到函数的下一次调用,在每次调用该函数时使该变量的值加1,就可以统计被调用的次数。#include<iostream>usingnamespacestd;voidfun(){staticn=0;n++;cout<<"本函数被调用了"<<n<<"次"<<endl;}第九十四页,共123页。voidfun1(){inti; for(i=1;i<=2;i++) fun();}intmain(){inti;for(i=1;i<=3;i++) fun(); fun1(); return1;}第九十五页,共123页。5.9程序设计实例5.9.1使用递归求斐波那契序列的前30项【例5-19】使用递归调用的方法计算Fibonacci数列的前30项,每行显示7个。斐波那契数列的前几项是:1、1、2、3、5、8、13、21,该数列的规律是前两项为1,从第三项开始,每一项是其前两项之和,对于从第三项开始的计算可以使用递归调用的方法。第九十六页,共123页。【源程序】#include<iostream>usingnamespacestd;intfib(intn)//计算Fibonacci数列的函数{if(n==0||n==1)//数列前2项直接赋值

return1;elsereturnfib(n-1)+fib(n-2); //从第3项起递归调用来计算}第九十七页,共123页。voidmain(){inti;for(i=0;i<30;i++){if(i%7==0) cout<<endl; //每行显示7项 cout<<fib(i)<<"\t";}}第九十八页,共123页。5.9.2求非线性方程的根【例5-20】用二分迭代法求方程2x3-4x2+3x-6=0在(-10,10)之间的根。【例5-21】用弦截法求方程x3-5x2+16x-80=0在(2,6)之间的根。第九十九页,共123页。【例5-20】用二分迭代法求方程2x3-4x2+3x-6=0在(-10,10)之间的根。用二分法求方程根的前提是方程f(x)=0有两个粗略的解x1和x0,这就是初值,对初值要求:(1)f(x1)和f(x0)符号相反;(2)f(x)在(x1,x0)内单调升或单调降。【算法描述】(1)取两点区间的中点:x=(x1+x0)/2,这就是迭代公式。(2)测试中点的函数值f(x)是否满足精度要求,这是迭代条件,若满足则用x作为方程的近似根,迭代过程结束;(3)如果不满足精度,则用x与x1和x0中的一个组成新的区间,重复过程(2)不断地缩小区间。在组成新区间时,如果中点的函数值与x1点的函数值同号,则新区间为(x,x0),否则为(x1,x)。第一百页,共123页。【源程序】#include<cmath>#include<iostream>usingnamespacestd;doublefun(doublex){ return((2*x-4)*x+3)*x-6;}第一百零一页,共123页。intvoidmain(){ doubleeps=1e-5; doublex0=-10,x1=10,x,mid,mid0; x=(x0+x1)/2; mid=fun(x); while(fabs(mid)>eps)//循环执行(即迭代)的条件

{ mid0=fun(x0);第一百零二页,共123页。 if(mid0*mid<0)//判断x0的函数值与中点的函数值是否同号

x1=x; else x0=x; x=(x0+x1)/2; mid=fun(x);} cout<<"root="<<x; return1;}第一百零三页,共123页。【例5-21】用弦截法求方程x3-5x2+16x-80=0在(2,6)之间的根。用弦截法求方程根的前提是方程f(x)=0有两个粗略的解x1和x2,它们满足以下条件:(1)f(x1)和f(x2)符号相反;(2)f(x)在(x1,x2)内单调升或单调降。第一百零四页,共123页。算法(1)求x1,x2两点连线与x轴的交点x,计算方法是对两点式直线方程令y=0,得:x=(x1*f(x2)-x2*f(x1))/(f(x2)-f(x1))这就是计算近似根的迭代公式。(2)判断新点x的函数值是否满足精度要求(例如小于0.0001),如果是,则用x作为方程的近似根,迭代过程结束;(3)如果不满足要求,则用x与x1和x2中的一个组成新的区间,重复过程(2)不断地缩小区间。在组成新区间时,如果x的函数值与x1点的函数值同号,则新区间为(x,x2),否则为(x1,x)。第一百零五页,共123页。【源程序】#include<cmath>#include<iostream>usingnamespacestd;doublefun(doublex)//计算方程f(x)的函数{doubley; y=((x-5.0)*x+16.0)*x-80.0; returny;}第一百零六页,共123页。intmain(){ doublex1=2,x2=6,x,y,y1;y1=fun(x1); do {x=(x1*fun(x2)-x2*fun(x1))/(fun(x2)-fun(x1));//迭代公式

y=fun(x);第一百零七页,共123页。 if(y*y1>0)//判断y与y1的值是否同号 { y1=y;x1=x; } else x2=x; }while(fabs(y)>=0.0001);//迭代条件 cout<<"root="<<x;return1;}第一百零八页,共123页。5.9.3有趣的数【例5-22】找出2~200之间的所有孪生素数。【例5-23】使用200以内的偶数验证哥德巴赫猜想。第一百零九页,共123页。【例5-22】找出2~200之间的所有孪生素数。孪生素数指间隔为2的相邻素数,例如3和5,5和7,其中最小的孪生素数是3和5。解决方法编写一个函数用来判断某个整数是否为素数,该函数的类型为bool型,如果判断结果为素数则返回true,否则返回false在主函数中调用该函数,判断某个整数i和i+2是否同时为素数。第一百一十页,共123页。【源程序】#include"iostream"usingnamespacestd;boolisprime(intn) //判断某个整数是否为素数的函数{inti;for(i=2;i<n;i++)if(n%i==0)

returnfalse;//找到n的某个因子后返回false值returntrue;//没有找到n的因子时返回true值}第一百一十一页,共123页。intmain(){inti;cout<<"

温馨提示

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

评论

0/150

提交评论