return0;
}
当在键盘上输入69后程序的执行结果是:
70
x=10y=60
a=0b=0
程序中主函数先调用fun1(),实参是6,将实参值传给形参s(即s=6),函数fun1中x值为10,y值为60,return语句将x+y的和返回,fun1()结束。
主函数输出返回值之后,调用fun2(),在fun2()中输出全局变量x和y的值,之后返回主函数。
在主函数中输出全局变量a和b值。
由于a、b在声明时未赋初值,系统的默认值为0。
使用全局变量的说明:
在一个函数内部,既可以使用本函数定义的局部变量,也可以使用在此函数前定义的全局变量。
全局变量的作用是使得函数间多了一种传递信息的方式。
如果在一个程序中多个函数都要对同一个变量进行处理,即共享,就可以将这个变量定义成全局变量,使用非常方便,但副作用也不可低估。
过多地使用全局变量,会增加调试难度。
因为多个函数都能改变全局变量的值,不易判断某个时刻全局变量的值。
过多地使用全局变量,会降低程序的通用性。
如果将一个函数移植到另一个程序中,需要将全局变量一起移植过去,同时还有可能出现重名问题。
全局变量在程序执行的全过程中一直占用内存单元。
全局变量在定义时若没有赋初值,其默认值为0。
2、局部变量
⑴局部变量的作用域是在定义该变量的函数内部。
换句话说,局部变量只在定义它的函数内有效。
在一个子程序内定义的变量也是局部变量,其作用域是该子程序。
函数的形参也是局部变量。
⑵由于局部变量的作用域仅局限于本函数内部,所以,在不同的函数中变量名可以相同,它们分别代表不同的对象,在内存中占据不同的内存单元,互不干扰。
⑶一个局部变量和一个全局变量是可以重名的,在相同的作用域内局部变量有效时全局变量无效。
即局部变量可以屏蔽全局变量。
练习一:
编程求5!
+7!
+9!
+11!
的值。
练习二:
求正整数2和100之间的完全数。
完全数:
因子之和等于它本身的自然数,如6=1+2+3
练习三:
如果一个自然数是素数,且它的数字位置经过对换后仍为素数,则称为绝对素数,例如13。
试求出所有二位绝对素数。
第24课:
函数的综合运用
例1:
计算如图多边形的面积。
【问题分析】:
从图中可以看出,五边形的
面积是三个三角形面积之和。
【算法设计】:
五边形的5条边分别设为
b1、b2、b3、b4、b5,两条对角线分别为
b6、b7,然后利用海伦公式分别求出三个
三角形的面积,三个三角形的面积之和即为
五边形的面积。
参考程序:
#include
#include
#include
usingnamespacestd;
doublearea(doublea,doubleb,doublec);
intmain()
{
doubleb1,b2,b3,b4,b5,b6,b7,s;
cout<<"pleaseinputb1,b2,b3,b4,b5,b6,b7:
"<cin>>b1>>b2>>b3>>b4>>b5>>b6>>b7;
s=area(b1,b5,b6)+area(b2,b6,b7)+area(b3,b4,b7);
printf("s=%10.3lf\n",s);
return0;
}
doublearea(doublea,doubleb,doublec)
{
doublep=(a+b+c)/2;
returnsqrt(p*(p-a)*(p-b)*(p-c));
}
此程序中的函数位置与前面的函数不同,放在了主程序的后面。
只在主程序前面放了一个函数的声明。
如果不做声明就放在了主程序后,是会出错的。
六、函数的声明
调用函数之前先要声明函数原型。
在主调函数中,或所有函数定义之前,按如下形式声明:
类型说明符被调函数名(含类型说明的形参表);
如果是在所有函数定义之前声明了函数原型,那么该函数原型在本程序文件中任何地方都有效,也就是说在本程序文件中任何地方都可以依照该原型调用相应的函数。
如果是在某个主调函数内部声明了被调用函数原型,那么该原型就只能在这个函数内部有效。
函数原型和函数定义在返回值类型、函数名和参数个数与类型必须完全一致,否则,就会发生编译错误。
下面对max()函数原型声明是合法的。
intmax(intx,inty);
也可以:
intmax(int,int);
可以看到函数原型声明与函数定义时的第一行类似,只多了一个分号,成为了一个声明语句而已。
2、函数的返回值
在组成函数体的各类语句中,值得注意的是返回语句return。
它的一般形式是:
return(表达式);
其功能是把程序流程从被调函数转向主调函数并把表达式的值带回主调函数,实现函数的返回。
所以,在圆括号表达式的值实际上就是该函数的返回值。
其返回值的类型即为它所在函数的函数类型。
当一个函数没有返回值时,函数中可以没有return语句(在TC++和VC++,函数类型定义为void,可以没有return语句;函数类型定义为int,必须有返回值),直接利用函数体的右花括号“}”,作为没有返回值的函数的返回。
也可以有return语句,但return后没有表达式。
返回语句的另一种形式是:
return;
这时函数没有返回值,而只把流程转向主调函数。
例2:
定义一个函数check(n,d),让它返回一个布尔值。
如果数字d在正整数n的某位中出现则送回true,否则送回false。
例如:
check(325719,3)==true;check(77829,1)==false;
【问题分析】:
本题是利用函数求位数是否相同的题目,函数的返回值为布尔(boolean)变量。
【算法设计】:
利用While循环语句,一位一位的取出给定数字n各位上的数,与给的数d比较,如果相等则函数返回true,否则则返回false。
参考程序:
#include
usingnamespacestd;
boolcheck(int,int);
intmain()
{
inta,b;
cout<<"inputa,b"<cin>>a>>b;
if(check(a,b)==true)cout<<"true"<elsecout<<"false"<return0;
}
boolcheck(intn,intd)
{
while(n)
{
inte=n%10;
n/=10;
if(e==d)returntrue;
}
returnfalse;
}
例3:
求正整数2和100之间的完全数。
完全数:
因子之和等于它本身的自然数,如6=1+2+3
【问题分析】:
首先判断2-100中的任何一个数是否为完全数,然后在主程序中输出该数。
【算法设计】:
由于2-100之间的任何一个数大于一半就不能被本数整数,所以在函数中判断是否为完全数时只须到一半(即i/2)即可。
参考程序:
#include
usingnamespacestd;
boolwqx(intn);
intmain()
{
inti;
for(i=2;i<=100;i++)
if(wqx(i))printf("%d",i);
return0;
}
boolwqx(intn)
{
intx,s=0;
for(x=1;x<=n/2;x++)
if(n%x==0)s=s+x;
if(s==n)returntrue;
returnfalse;
}
练习一:
求出1-n之间有所有素数之和。
练习二:
编写函数gcd,功能是利用辗转相除法求两个正整数m和n的最大公约数,并由函数值返回。
练习三:
编写一个求两个数约分,求互质数的程序。
第24课:
函数的嵌套和递归
一、函数的嵌套
函数的嵌套调用指的是一个函数调用另一个函数,而被调用函数又可调用其它函数。
例如,在调用A函数的过程中,可以调用B函数,在调用B函数的过程中,还可以调用C函数……当C函数调用结束后,返回到B函数,当B函数调用结束后,再返回到A函数。
这就是函数的嵌套调用过程。
例1:
函数的嵌套应用举例
【问题分析】:
主程序中调用函数1,函数1调用函数2,函数2调用函数3。
【算法设计】:
主程序调用无参数的函数p1(),在p1()中函数调用f(i),而函数f(i)中调用函数p2(i),函数逐级返回。
p2(i)返回f(i),f(i)返回到p1(),p1()返回到主函数。
参考程序:
#include
usingnamespacestd;
inti=10;
voidp2(inti1)
{
i1*=2;
cout<<"i1="<}
intf(inti)
{
p2(i);
return(3*i);
}
voidp1()
{
i=f(i);
}
intmain()
{
cout<<"i="<
p1();
cout<<"i="<
return0;
}
由上图来看,主程序调用无参函数p1,p1函数调用函数f,而函数f调用函数p2,它们的调用的基本规则是上一层调用下一层。
从上图来看,它们之间的关系是逐层相包,完全套住的。
套住其它函数的函数叫外层函数,被其它函数套住的函数叫内层函数。
对于多层嵌套来说,内层和外层是相对的。
二、函数的递归
1、欣赏图片
2、听一个古老的故事
Ø"从前有座山山上有座庙,庙里有个老和尚,老和尚在给小和尚讲故事:
Ø"从前有座山山上有座庙,庙里有个老和尚,老和尚在给小和尚讲故事:
Ø"从前有座山山上有座庙,庙里有个老和尚,老和尚在给小和尚讲故事:
……
Ø
"从前有座山山上有座庙,庙里有个老和尚,老和尚在给小和尚讲故事:
Ø这就是递归
3、递归的概念
函数直接或间接地自己调用自己,称为递归调用。
递归形式一般有两种——间接递归和直接递归。
间接递归——子程序A调用子程序B,子程序B又调用子程序A
在现实生活中,通过间接递归计算两个并列函数或过程的情况并不多见,比较多的递归方式是直接递归。
直接递归——子程序要求自己调用自己
我们研究的是直接递归,它是设计和描述算法的一种有力的工具。
递归结束的要件:
满足某个条件后递归终止。
4、递归所能解决的问题
递归通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。
递归的能力在于用有限的语句来定义对象的无限集合。