if(n==0)return1;
elseif(n%2!
=0)returnx*sqr(p(x,n/2));
elsereturnsqr(p(x,n/2));
}
intmain(){
cout<
return0;
}
答案:
in-process:
x=2n=13
in-process:
x=2n=6
in-process:
x=2n=3
in-process:
x=2n=1
in-process:
x=2n=0
8192
图解递归,共五层,f是回归时产生:
xnf
2
13
8192
f=x*sqr(下一层的f)
2
6
64
f=sqr(下一层的f)
2
3
8
f=x*sqr(下一层的f)
2
1
2
f=x*sqr(下一层的f)
2
0
1
f=1
3.2简答题
3.2.1函数的实参和形参怎样对应?
实参和形参数目必须一致吗?
什么情况下可以不同?
答:
实参和形参的个数和排列顺序应一一对应,并且对应参数应类型匹配(赋值兼容),当有缺省参数时可以不同。
3.2.2函数和内联函数的执行机制有何不同?
定义内联函数有何意义?
又有何要求?
答:
内联函数的调用机制与一般函数不同,编译器在编译过程中遇到inline时,为该函数建立一段代码,而后在每次调用时直接将该段代码嵌入到调用函数中,从而将函数调用方式变为顺序执行方式,这一过程称为内联函数的扩展或内联。
内联函数的实质是牺牲空间来换取时间。
因inline指示符对编译器而言只是一个建议,编译器也可以选择忽略该建议,内联函数只适用于功能简单,代码短小而又被重复使用的函数。
函数体中包含复杂结构控制语句,如switch、复杂if嵌套、while语句等,以及无法内联展开的递归函数,都不能定义为内联函数,即使定义,系统也将作为一般函数处理。
3.2.3全局变量和全局静态变量的区别在哪里?
为什么提倡尽量使用局部变量?
答:
有static修饰的全局变量只能在定义它的文件中可见,在其他文件中不可见,而非静态的全局变量则可以被其他程序文件访问,但使用前必须用extern说明。
局部变量具有局部作用域使得程序在不同块中可以使用同名变量。
这些同名变量各自在自己的作用域中可见,在其它地方不可见。
所以提倡尽量使用局部变量
3.2.4函数重载的作用是什么?
满足什么条件的函数才可以成为重载函数?
重载函数在调用时是怎样进行对应的?
答:
函数重载可以定义几个功能相似,而参数类型不同使用相同的函数名的函数,以适应不同情况下自动选用不同函数进行操作。
函数重载的好处在于,可以用相同的函数名来定义一组功能相同或类似的函数,程序的可读性增强。
在定义重载函数时必须保证参数类型不同,仅仅返回值类型不同是不行的。
当某个函数中调用到重载函数时,编译器会根据实参的类型去对应地调用相应的函数。
匹配过程按如下步骤进行:
(1)如果有严格匹配的函数,就调用该函数;
(2)参数内部转换后如果匹配,调用该函数;
(3)通过用户定义的转换寻求匹配。
3.2.5多文件结构的程序是如何进行管理并运行的?
采用多文件结构有什么好处?
答:
多文件结构通过工程进行管理,在工程中建立若干用户定义的头文件.h和源程序文件.cpp。
头文件中定义用户自定义的数据类型,所有的程序实现则放在不同的源程序文件中。
编译时每个源程序文件单独编译,如果源程序文件中有编译预处理指令,则首先经过编译预处理生成临时文件存放在内存,之后对临时文件进行编译生成目标文件.obj,编译后临时文件撤销。
所有的目标文件经连接器连接最终生成一个完整的可执行文件.exe。
多文件结构管理程序的好处是十分明显的。
首先,可以避免重复性的编译,如果修改了个别函数,那么只需将这些函数所在的文件重新编译即可;其次,将程序进行合理的功能划分后,更容易设计、调试和维护;另外,通常把相关函数放在一个文件中,这样形成一系列按照功能分类的文件,便于为其他程序文件使用。
3.2.6宏定义与常量定义从作用及效果上看是一样的,二者是否完全相同?
答:
完全不同。
不带参宏定义与const说明符定义常量从效果上看是一样的,但它们的机制不同。
首先宏定义是在预处理阶段完成,而const定义则是在编译阶段实现。
其次宏定义只是一种简单的字符串替代,不会为字符串分配内存单元,替代过程也不作语法检查,即使指令中的常量字符串不符合常量要求,预处理的替代过程也照样按指令给出的格式进行。
而const定义则是象定义一个变量一样定义一个常量标识符,系统要按照类型要求为该标识符分配内存单元,同时在将常量放入单元时进行类型检查,如果类型不匹配,类型相容的会进行系统的类型转换,不相容的则要提示错误。
二.编程与综合练习题
3.3设计函数,将小写英文字符变为对应的大写字符。
解:
小写字母比大写字母ASCII码值大32,或写作ch=ch-‘a’+’A’;
#include
usingnamespacestd;
charcapitalize(charch){
if(ch>='a'&&ch<='z')returnch-'a'+'A';
elsereturnch;
}
intmain(){
inti=0;
charcp[30];
cout<<"请输入包含小写字母的句子:
"<cin.getline(cp,30);
while(cp[i]!
='\0')cout<cout<return0;
}
3.4设计两个函数,分别求两个数的最大公约数和最小公倍数。
解:
可用穷举法求最大公约数(从大到小找到的第1个公约数)和最小公倍数(从小到大找到的第1个公倍数)。
#include
usingnamespacestd;
MaxCommonDevisor(intn,intm){
inti;
for(i=n;i>=1;i--)
if(n%i==0&&m%i==0)break;
returni;
}
MinCommonMultiple(intn,intm){
inti;
for(i=n;i<=n*m;i++)
if(i%n==0&&i%m==0)break;
returni;
}
intmain(){
inti,j;
cout<<"请输入两个整数:
"<cin>>i>>j;
cout<<"最大公约数:
"<<<'\t'<<"最小公倍数:
"<return0;
}
3.5设计函数digit(num,k),返回整数num从右边开始的第k位数字的值。
例如:
digit(4647,3)=6
digit(23523,7)=0
解:
把整数转换为数串,放在一个整型数组中。
#include
usingnamespacestd;
digit(intnum,intk){
ints[10]={0,0,0,0,0,0,0,0,0,0};
inti=0;
do{//先把整数转换为数字串
s[i]=num%10;
num/=10;
i++;
}while(num>0);
if(k<=i)returns[k-1];//题目中位数的下标从1开始,而数组下标从0开始
elsereturn0;
}
intmain(){
cout<<"digit(4647,3)="<cout<<"digit(23523,7)="<return0;
}
3.6设计函数factors(num,k),返回整数num中包含因子k的个数,如果没有该因子,则返回0。
解:
必须先判断整数m能否被k整除。
#include
usingnamespacestd;
factors(intnum,intk){//缺省返回值为整型
intcount=0;
while(num%k==0){
count++;
num/=k;
}
returncount;
}
intmain(){
cout<<"factors(1875,5)="<cout<<"factors(64,3)="<return0;
}
3.7歌德巴赫猜想指出:
任何一个充分大的偶数都可以表示为两个素数之和。
例如:
4=2+26=3+38=3+5……50=3+47
将450之间的所有偶数用两个素数之和表示。
判断一个整数是否为素数用函数完成。
解:
用prime()函数判断是否素数,用穷举法。
歌德巴赫猜想验证也用穷举法,在所有组合中找两个数均为素数者。
#include
#include
usingnamespacestd;
boolprime(intm){
if(m==1||m==0)returnfalse;
if(m==2)returntrue;
intk=(int)sqrt(m);
for(inti=2;i<=k;i++)//穷举法
if(m%i==0)break;
if(i>k)returntrue;
elsereturnfalse;
}
intmain(){
for(intn=4;n<=50;n+=2){
for(inti=2;i<=n/2;i++)
if(prime(i)&&prime(n-i))cout<}
return0;
}
3.8设计函数打印直方图,直方图宽度为3行,每列代表数据1%。
如下面的图形表示10%。
|
|**********
|**********
|**********
|
解:
为简单将a%用a表示。
#include
usingnamespacestd;
voidPrintDiagram(intm){
inti;
for(i=0;i<3;i++){
for(intj=0;jcout<}
cout<}
intmain(){
PrintDiagram(10);
PrintDiagram(15);
PrintDiagram(7);
return0;
}
3.9定义递归函数实现下列Ackman函数:
其中m、n为正整数。
设计程序求Acm(2,1),Acm(3,2)。
解:
递归函数实现非常简单,按公式写即可。
#include
usingnamespacestd;
Acm(intm,intn){
if(m==0)returnn+1;
if(n==0)returnAcm(m-1,1);
returnAcm(m-1,Acm(m,n-1));
}
intmain(){
cout<<"Acm(2,1)="<cout<<"Acm(3,2)="<return0;
}
3.10用递归函数实现勒让德多项式:
在主函数中求P4(1.5)。
解:
把勒让德多项式的阶和自变量都作为参数。
#include
usingnamespacestd;
doubleP(intn,doublex){
if(n==0)return1;
if(n==1)returnx;
return((2*n-1)*x*P(n-1,x)-(n-1)*P(n-2,x))/n;
}
intmain(){
cout<<"P(4,1.5)="<
return0;
}
3.11定义内联函数实现求三个实数中的最大值。
解:
内联函数只适用于功能简单,代码短小而又被重复使用的函数。
函数体中包含复杂结构控制语句,如switch、复杂if嵌套、while语句等,以及无法内联展开的递归函数,都不能定义为内联函数,即使定义,系统也将作为一般函数处理。
#include
usingnamespacestd;
inlinemax(inta,intb,intc){
if(a>b&&a>c)returna;
if(b>a&&b>c)returnb;
returnc;
}
intmain(){
cout<return0;
}
3.12定义内联函数,判断一个字符是否为数字字符。
解:
数字字符ASCII码值是连在一起的,可用ch>='0'&&ch<='9'来判断。
#include
usingnamespacestd;
inlineboolIfDigitChar(charch){
if(ch>='0'&&ch<='9')return1;
elsereturn0;
}
intmain(){
charch;
cout<<"请输入一个字符(输入“!
”停止)"<cin>>ch;
while(ch!
='!
'){
if(IfDigitChar(ch))cout<elsecout<cout<<"请输入一个字符(输入“!
”停止)"<cin>>ch;
}
return0;
}
3.13设计两个重载函数,分别求两个整数相除的余数和两个实数相除的余数。
两个实数求余定义为实数四舍五入取整后相除的余数。
解:
实数四舍五入取整,正数是+0.5取整,负数是-0.5取整。
#include
#include
usingnamespacestd;
mod(intn,intm){
returnn%m;
}
round(doublex){//四舍五入函数
if(x>=0)returnint(x+0.5);
elsereturnint(x-0.5);
}
mod(doublex,doubley){
returnround(x)%round(y);
}
intmain(){
cout<<"mod(8,3)="<cout<<"mod(8.2,3.6)="<cout<<"mod(-8.2,-2.6)="<return0;
}
3.14建立一个头文件area.h,在其中定义两个面积函数area(),分别用来计算半径为r的圆的面积和边长为a和b的矩形面积。
另外建立一个实现文件area.cpp,在其中定义主函数。
通过包含area.h,输入数据并输出圆和矩形的面积。
解:
两个面积函数area(),一个是单参数,一个是双参数。
//头文件area.h
doublearea(doubler){
return3.14*r*r;
}
doublearea(doublea,doubleb){
returna*b;
}
//实现文件area.cpp
#include
usingnamespacestd;
#include"ep3_14.h"
intmain(){
doublea,b,r;
cout<<"inputradius:
"<cin>>r;
cout<<"inputsidelength:
"<cin>>a>>b;
cout<<"area("<cout<<"area("<return0;
}
3.15下面递归函数执行结果是什么?
1)voidp1(intw){
inti;
if(w>0){
for(i=0;icout<p1(w-1);
}
}
调用p1(4)。
答:
用调用树来解答,如下图,注意打印是在递归调用之前:
打印:
4444
333
22
1
2)voidp2(intw){
inti;
if(w>0){
p2(w-1);
for(i=0;icout<p2(w-1);
}
}
调用p2(4)。
答:
用调用树来解答,如下图,注意打印是在两次递归调用之间:
打印:
1
22
1
333
1
22
1
4444
1
22
1
333
1
22
1
3)voidp3(intw){
inti;
if(w>0){
for(i=0;icout<p3(w-1);
p3(w-2);
}
}
调用p3(4)。
答:
用调用树来解答,如下图,注意打印是在两次递归调用之前:
打印:
4444
333
22
1
1
22
1
4)voidp4(intw){
inti;
if(w>0){
for(i=0;icout<p4(w-1);
for(i=0;icout<}
}
调用p4(4)。
答:
用调用树来解答,如下图,注意打印是在递归调用之前和之后各一次:
打印:
4444
333
22
1
1
22
333
4444