博文
C++ 入门 第四章 4.10 函数的递归调用[例题2](2008-09-10 14:17:00)
摘要:
例4.11 用递归方法求n!。
求n!可以用递推方法,即从1开始,乘2,再乘3……一直乘到n。
求n!也可以用递归方法,即5!=4!×5,而4!=3!×4,…,1!=1。可用下面的递归公式表示:
n!= 1 (n=0,1)
n·(n-1)! (n>1)
有了例4.10的基础,很容易写出本题的程序:
#include <iostream>
using namespace std;
long fac(int); //函数声明
int main( )
{int n; //n为需要求阶乘的整数
long y; //y为存放n!的变量
cout<<″please input an integer :″; //输入的提示 &nb......
C++ 入门 第四章 4.10 函数的递归调用[例题](2008-09-10 14:16:00)
摘要:
例4.10 有5个人坐在一起,问第5个人多少岁?他说比第4个人大两岁。问第4个人岁数,他说比第3个人大两岁。问第3个人,又说比第2个人大两岁。问第2个人,说比第1个人大两岁。最后问第1个人,他说是10岁。请问第5个人多大?
每一个人的年龄都比其前1个人的年龄大两岁。即
age(5)=age(4)+2
age(4)=age(3)+2
age(3)=age(2)+2
age(2)=age(1)+2
age(1)=10
可以用式子表述如下:
age(n)=10 (n=1)
age(n)=age(n-1)+2 (n>1)
可以看到,当n>1时,求第n个人的年龄的公式是相同的。因此可以用一个函数表示上述关系。图4.11表示求第5个人年龄的过程。
可以写出以下C++程序,其中的age函数用来实现上述递归过程。
#include <iostream>
using namespace std;
int age(int); //函数声明
int main( ) //主函数
{ cout<<age(5)<<endl;
ret......
C++ 入门 第四章 4.10 函数的递归调用(2008-09-10 14:14:00)
摘要:
在调用一个函数的过程中又出现直接或间接地调用该函数本身,称为函数的递归(recursive)调用。C++允许函数的递归调用。例如:
int f(int x)
{int y,z;
z=f(y); //在调用函数f的过程中,又要调用f函数
return (2*z);
}
以上是直接调用本函数,见图4.9。
图4.10表示的是间接调用本函数。在调用f1函数过程中要调用f2函数,而在调用f2函数过程中又要调用f1函数。
图4.9
图4.10
从图上可以看到,这两种递归调用都是无终止的自身调用。显然,程序中不应出现这种无终止的递归调用,而只应出现有限次数的、有终止的递归调用,这可以用if语句来控制,只有在某一条件成立时才继续执行递归调用,否则就不再继续。
包含递归调用的函数称为递归函数。
......
C++ 入门 第四章 4.9 函数的嵌套调用[3](2008-09-08 17:26:00)
摘要:
(4) 在root函数中要用到求绝对值的函数fabs,它是对双精度数求绝对值的系统函数。它属于数学函数库,故在文件开头用#include <cmath>把有关的头文件包含进来。 ......
C++ 入门 第四章 4.9 函数的嵌套调用[2](2008-09-08 17:25:00)
摘要:
(2) 用函数xpoint (x1,x2)来求(x1,f(x1))和(x2,f(x2))的连线与x轴的交点x的坐标。
(3) 用函数root(x1,x2)来求(x1,x2)区间的那个实根。显然,执行root函数的过程中要用到xpoint函数,而执行xpoint函数的过程中要用到f函数。
根据以上算法,可以编写出下面的程序:
#include <iostream>
#include <iomanip>
#include <cmath>
using namespace std;
double f(double); //函数声明
double xpoint(double, double); //函数声明
double root(double, double); //函数声明
int main( )
{ double x1,x2,f1,f2,x;
do
{cout<<″input x1,x2:″;
cin>>x1>>x2;
f1=f(x1);
f2=f(x2);
} while(f1*f2>=0);
x=root(x1,x2);
cout<<setiosflags(ios∷fixed)<<setprecision(7);
//指定输出7位小数
cout<<″A root of equation is ″<<x<<endl;
return 0;
}
double f(double x)  ......
C++ 入门 第四章 4.9 函数的嵌套调用[1](2008-09-08 17:24:00)
摘要:
C++不允许对函数作嵌套定义,也就是说在一个函数中不能完整地包含另一个函数。在一个程序中每一个函数的定义都是互相平行和独立的。
虽然C++不能嵌套定义函数,但可以嵌套调用函数,也就是说,在调用一个函数的过程中,又调用另一个函数。见图4.6。
在程序中实现函数嵌套调用时,需要注意的是: 在调用函数之前,需要对每一个被调用的函数作声明(除非定义在前,调用在后)。
例4.9 用弦截法求方程f(x)=x3-5x2+16x-80=0的根。
这是一个数值求解问题,需要先分析用弦截法求根的算法。根据数学知识,可以列出以下的解题步骤:
(1) 取两个不同点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,见图4.7。
x点坐标可用下式求出:
x=x1·f(x2)-x2·f(x1)
f(x2)-f(x1)
再从x求出f(x)。
(3) 若f(x)与f(x1)同符号,则根必在(x, x2)区间内,此时将x作为新的x1。如果f(x)与f(x2)同符号,则表示根在( x1,x)区间内,将x作为新的x2。
(4) 重复步骤 (2) 和 (3), 直到 |f(x)|<ξ为止, ξ为一个很小的正数, 例如10-6。此时认为 f(x)≈0。
这就是弦截法的算法,在程序中分别用以下几个函数来实现以上有关部分功能:
(1) 用函数f(x)代表x的函数:x3-5x2+16x-80。
......
C++入门 第四章 4.8 有默认参数的函数(2008-09-07 17:54:00)
摘要:
一般情况下,在函数调用时形参从实参那里取得值,因此实参的个数应与形参相同。有时多次调用同一函数时用同样的实参,C++提供简单的处理办法,给形参一个默认值,这样形参就不必一定要从实参取值了。如有一函数声明
float area(float r=6.5);
指定r的默认值为6.5,如果在调用此函数时,确认r的值为6.5,则可以不必给出实参的值,如
area( ); //相当于area(6.5);
如果不想使形参取此默认值,则通过实参另行给出。如area(7.5); //形参得到的值为7.5,而不是6.5
这种方法比较灵活,可以简化编程,提高运行效率。
如果有多个形参,可以使每个形参有一个默认值,也可以只对一部分形参指定默认值,另一部分形参不指定默认值。如有一个求圆柱体体积的函数,形参h代表圆柱体的高,r为圆柱体半径。函数原型如下:
float volume(float h,float r=12.5); //只对形参r指定默认值12.5
函数调用可以采用以下形式:
volume(45.6); ......
C++ 入门教程 第四章 4.7 函数模板(2008-09-07 17:53:00)
摘要:
C++提供了函数模板(function template)。所谓函数模板,实际上是建立一个通用函数,其函数类型和形参类型不具体指定,用一个虚拟的类型来代表。这个通用函数就称为函数模板。凡是函数体相同的函数都可以用这个模板来代替,不必定义多个函数,只需在模板中定义一次即可。在调用函数时系统会根据实参的类型来取代模板中的虚拟类型,从而实现了不同函数的功能。看下面的例子就清楚了。
例4.7 将例4.6程序改为通过函数模板来实现。#include <iostream>
using namespace std;
template<typename T> //模板声明,其中T为类型参数
T max(T a,T b,T c) //定义一个通用函数,用T作虚拟的类型名
{if(b>a) a=b;
if(c>a) a=c;
return a;
}
int main( )
{int i1=185,i2=-76,i3=567,i;
double d1=56.87,d2=90.23,d3=-3214.78,d;
long g1=67854,g2=-912456,g3=673456,g;
i=max(i1,i2,i3); //调用模板函数,此时T被int取代
d=max(d1,d2,d3); //调用模板函数,此时T被double取代
g=max(g1,g2,g3); //调用模板函数,此时T被long取代
......
C++ 入门 第四章 4.6 函数的重载(2008-09-06 11:21:00)
摘要:
在编程时,有时我们要实现的是同一类的功能,只是有些细节不同。例如希望从3个数中找出其中的最大者,而每次求最大数时数据的类型不同,可能是3个整数、3个双精度数或3个长整数。程序设计者往往会分别设计出3个不同名的函数,其函数原型为:
int max1(int a,int b, int c); //求3个整数中的最大者
double max2(double a,double b,double c); //求3个双精度数中最大者
long max3(long a,long b,long c); //求3个长整数中的最大者
C++允许用同一函数名定义多个函数,这些函数的参数个数和参数类型不同。这就是函数的重载(function overloading)。即对一个函数名重新赋予它新的含义,使一个函数名可以多用。
对上面求最大数的问题可以编写如下的C++程序。
例4.5 求3个数中最大的数(分别考虑整数、双精度数、长整数的情况)。
#include <iostream>
using namespace std;
int main( )
{int max(int a,int b,int c); //函数声明
double max(double a,double b,double c); //函数声明
long max(long a,long b,long c); //函数声明
int i1,i2,i3,i; &......
C++ 入门 第四章 4.5 内置函数(2008-09-06 11:20:00)
摘要:
调用函数时需要一定的时间和空间的开销。图4.5表示函数调用的过程:
C++提供一种提高效率的方法,即在编译时将所调用函数的代码直接嵌入到主调函数中,而不是将流程转出去。这种嵌入到主调函数中的函数称为内置函数(inline function),又称内嵌函数。在有些书中把它译成内联函数。
指定内置函数的方法很简单,只需在函数首行的左端加一个关键字inline即可。
例4.4 函数指定为内置函数。
#include <iostream>
using namespace std;
inline int max(int,int, int); //声明函数,注意左端有inline
int main( )
{int i=10,j=20,k=30,m;
m=max(i,j,k);
cout<<″max=″<<m<<endl;
return 0;
}
inline int max(int a,int b,int c) //定义max为内置函数
{if(b>a) a=b; //求a,b,c中的最大者
if(c>a) a=c;
return a;
}
由于在定义函数时指定它为内置函数,因此编译系统在遇到函数调用“max(i,j,k)”时,就用max函数体的代码代替“max(i,j,k)”,同时将实参代替形参。这样,程序第6行 “m=max(i,j,k);”就被置换成
if (j>i) i=j;
if(k>i) i=k;
m=i;
......