第三章 函数习题
一.基本概念与基础知识自测题
3.1 填空题
3.1.1 被定义为形参的是在函数中起  (1) 作用的变量,形参只能用 (2) 表示。实参的作用是 (3) ,实参可以用 (4) 、 (5) 、  (6) 表示。
答案:
(1)自变量
(2)变量名
(3)将实际参数的值传递给形参
(4)具有值的变量
(5)常量
(6)表达式
3.1.2 局部域包括 (1) 、 (2) 和 (3)  。使用局部变量的意义在于 (4) 。
答案:
(1)块域
(2)函数域
(3)函数原型域
(4)局部变量具有局部作用域使得程序在不同块中可以使用同名变量
3.1.3 静态局部变量存储在 (1) 区,在 (2) 时候建立,生存期为(3) ,如定义时未显式初始化,则其初值为  (4) 。
答案:
(1)全局数据区
(2)编译
(3)全局生存期
(4)全0
3.1.4局部变量存储在 (1) 区,在 (2) 时候建立,生存期为(3) ,如定义时未显式初始化,则其初值为 (4) 。
答案:
(1)栈
(2)在函数或块开始执行时
(3)函数或块的执行期
(4)随机值
3.1.5 编译预处理的作用是 (1) ,预处理指令的标志是 (2) 。多文件系统中,程序由  (3)  来管理,用户自定义头文件中通常定义一些 (4) 。
答案:
(1)将源程序文件进行处理,生成一个中间文件,编译系统对此中间文件进行编译并生成目标代码
(2)#
(3)工程文件
(4)用户构造的数据类型(如枚举类型),外部变量,外部函数、常量和内联函数等具有一定通用性或常用的量
3.1.6 设有函数说明如下:
  int f(int x, int y){ return x%y+1; }
  假定a=10,b=4,c=5,下列语句的执行结果分别是 (1) 和 (2) 。
  (1)  cout<<f(a,b)+f(a,c);    (2)  cout<<f(f(a+c,b),f(b,c));
解答:
(1)答案:4
(2)答案:5
3.1.7下列程序的输出结果分别为  (1) 和  (2)  。
(1)
#include<iostream>
using namespace std;
int a,b;
void f(int j){
static int i=a;  //注意静态局部变量
int m,n;
m=i+j;  i++;  j++;  n=i*j;  a++;
cout<<"i="<<i<<'\t'<<"j="<<j<<'\t';
cout<<"m="<<m<<'\t'<<"n="<<n<<endl;
}
int main(){
a=1; b=2;
f(b);  f(a);
cout<<"a="<<a<<'\t'<<"b="<<b<<endl;
return 0;
}
解:
答案:
i=2  j=3  m=3  n=6    (对应蓝)
i=3  j=3  m=4  n=9    (对应绿)
a=3  b=2
(2)
#include<iostream>
using namespace std;
float sqr(float a){return a*a;}
float p(float x,int n){
cout<<"in-process:"<<"x="<<x<<'\t'<<"n="<<n<<endl;
if(n==0) return 1;
else if(n%2!=0) return x*sqr(p(x,n/2));
else return sqr(p(x,n/2));
}
int main(){
cout<<p(2.0,13)<<endl;
return 0;
}
图解递归,共五层,返回值是回归时产生:
答案:
in-process:x=2  n=13
in-process:x=2  n=6
in-process:x=2  n=3
in-process:x=2  n=1
in-process:x=2  n=0
8192
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<iostream>
using namespace std;
char capitalize(char ch){
if(ch>='a'&&ch<='z') return ch-'a'+'A';
else return ch;
}
int main(){
int i=0;
char cp[30];
cout<<"请输入包含小写字母的句子:"<<endl;
while(cp[i]!='\0') cout<<capitalize(cp[i++]);
cout<<endl;
return 0;
}
3.4 设计两个函数,分别求两个数的最大公约数和最小公倍数。
解:可用穷举法求最大公约数(从大到小到的第1个公约数)和最小公倍数(从小到大到的第1个公倍数)。
#include<iostream>
using namespace std;
MaxCommonDevisor(int n,int m){
int i;
  for( i=n;i>=1;i--)
if(n%i==0 && m%i==0) break;
return i;
}
MinCommonMultiple(int n,int m){
int i;
  for(i=n;i<=n*m;i++)
if(i%n==0 && i%m==0) break;
return i;
}
int main(){
int i,j;
cout<<"请输入两个整数:"<<endl;
cin>>i>>j;
cout<<"最大公约数:"<<MaxCommonDevisor(i,j)
<<'\t'<<"最小公倍数:"<<MinCommonMultiple(i,j)<<endl;
return 0;
}
3.5 设计函数digit(num,k),返回整数num从右边开始的第k位数字的值。例如:
  digit(4647,3)=6
  digit(
23523,7)=0
解:把整数转换为数串,放在一个整型数组中。
#include<iostream>
using namespace std;
digit(int num,int k){
int s[10]={0,0,0,0,0,0,0,0,0,0};
int i=0;
do{//先把整数转换为数字串
s[i]=num%10;
num/=10;
i++;
}while(num>0);
if(k<=i) return s[k-1];  //题目中位数的下标从1开始,而数组下标从0开始
else return 0;
}
int main(){
cout<<"digit(4647,3)="<<digit(4647,3)<<endl;
cout<<"digit(23523,7)="<<digit(23523,7)<<endl;
return 0;
}
3.6 设计函数factors(num,k),返回整数num中包含因子k的个数,如果没有该因子,则返回0。
解:必须先判断整数m能否被k整除。
#include<iostream>
using namespace std;
factors(int num,int k){//缺省返回值为整型
int count=0;
while(num%k==0){
count++;
num/=k;
}
return count;
}
int main(){
cout<<"factors(1875,5)="<<factors(1875,5)<<endl;
cout<<"factors(64,3)="<<factors(64,3)<<endl;
return 0;
}
3.7 歌德巴赫猜想指出:任何一个充分大的偶数都可以表示为两个素数之和。例如:
  4=2+2  6=3+3  8=3+5  … …  50=3+47
  将4?50之间的所有偶数用两个素数之和表示。判断一个整数是否为素数用函数完成。
解:用prime()函数判断是否素数,用穷举法。歌德巴赫猜想验证也用穷举法,在所有组合中两个数均为素数者。
#include<iostream>
#include<cmath>
using namespace std;
bool prime(int m){
if(m==1||m==0) return false;
if(m==2) return true;
int k=(int)sqrt(m);
for(int i=2;i<=k;i++)//穷举法
if(m%i==0) break;
if(i>k) return true;
else return false;
}
int main(){
for(int n=4;n<=50;n+=2){
for(int i=2;i<=n/2;i++)
if(prime(i)&&prime(n-i)) cout<<n<<'='<<i<<'+'<<n-i<<endl;//列出所有可能组合
}
return 0;
}
3.8 设计函数打印直方图,直方图宽度为3行,每列代表数据1%。如下面的图形表示10%。
|
|**********
|**********
|**********
|
解:为简单将a%用a表示。
#include<iostream>
using namespace std;
void PrintDiagram(int m){
int i ;
cout<<'|'<<endl;
for(i=0;i<3;i++){
cout<<'|';
for(int j=0;j<m;j++) cout<<'*';
cout<<endl;
}
cout<<'|'<<endl;
}
int main(){
PrintDiagram(10);
PrintDiagram(15);
PrintDiagram(7);
return 0;
3.9 定义递归函数实现下列Ackman函数:
  其中m、n为正整数。设计程序求Acm(2,1),Acm(3,2)。
解:递归函数实现非常简单,按公式写即可。
#include<iostream>
using namespace std;
Acm(int m,int n){
if(m==0) return n+1;
if(n==0) return Acm(m-1,1);
return Acm(m-1,Acm(m,n-1));
}
int main(){
cout<<"Acm(2,1)="<<Acm(2,1)<<endl;
cout<<"Acm(3,2)="<<Acm(3,2)<<endl;
return 0;
}
3.10 用递归函数实现勒让德多项式:
  在主函数中求P4(1.5)。
解:把勒让德多项式的阶和自变量都作为参数。
#include<iostream>
using namespace std;
double P(int n,double x){
if(n
==0) return 1;
if(n==1) return x;
return ((2*n-1)*x*P(n-1,x)-(n-1)*P(n-2,x))/n;
}
int main(){
cout<<"P(4,1.5)="<<P(4,1.5)<<endl;
return 0;
}
3.11定义内联函数实现求三个实数中的最大值。
解:内联函数只适用于功能简单,代码短小而又被重复使用的函数。函数体中包含复杂结构控制语句,如switch、复杂if嵌套、while语句等,以及无法内联展开的递归函数,都不能定义为内联函数,即使定义,系统也将作为一般函数处理。
#include<iostream>
using namespace std;
inline max(int a,int b,int c){
if(a>b&&a>c) return a;
if(b>a&&b>c) return b;
return c;
}
int main(){
cout<<max(3,7,4)<<endl;
return 0;
}
3.12 定义内联函数,判断一个字符是否为数字字符。
解:数字字符ASCII码值是连在一起的,可用ch>='0'&&ch<='9'来判断。
#include<iostream>
using namespace std;
inline bool IfDigitChar(char ch){
if(ch>='0'&&ch<='9') return 1;
else return 0;
}
int main(){
char ch;
cout<<"请输入一个字符(输入“!”停止)"<<endl;
cin>>ch;
while(ch!='!'){
if(IfDigitChar(ch)) cout<<ch<<" is a digit char"<<endl;
else cout<<ch<<" is not a digit char"<<endl;
cout<<"请输入一个字符(输入“!”停止)"<<endl;
cin>>ch;
}
return 0;
}
3.13 设计两个重载函数,分别求两个整数相除的余数和两个实数相除的余数。两个实数求余定义为实数四舍五入取整后相除的余数。
解:实数四舍五入取整,正数是+0.5取整,负数是-0.5取整。
#include<iostream>
#include<cmath>
using namespace std;
mod(int n,int m){
return n%m;
}
round(double x){    //四舍五入函数
if(x>=0)  return int(x+0.5);
else  return int(x-0.5);
}
mod(double x,double y){
return round(x)%round(y);
}
int main(){
cout<<"mod(8,3)="<<mod(8,3)<<endl;
cout<<"mod(8.2,3.6)="<<mod(8.2,3.6)<<endl;
cout<<"mod(-8.2,-2.6)="<<mod(-8.2,-2.6)<<endl;
return 0;
}
注意:mod(double x,double y)形参类型不可以写成float,因为在入口函数中mod(8.2,3.6)的实参8.2、3.6都认为是double型常数,重载时系统不知应转换为float还是int,出现歧义。
3.14 建立一个头文件area.h,在其中定义两个面积函数area(),分别用来计算半径为r的圆的面积和边长为a和b的矩形面积。另外建立一个实现文件area.cpp,在其中定义主函数。通过包含area.h,输入数据
并输出圆和矩形的面积。
解:两个面积函数area(),一个是单参数,一个是双参数。
//头文件area.h
double area(double r){
return 3.14*r*r;
}
double area(double a,double b){
return a*b;
}
//实现文件area.cpp
#include<iostream>
using namespace std;
#include"area.h"
int main(){
double a,b,r;
cout<<"input radius:"<<endl;
cin>>r;
cout<<"input side length:"<<endl;
字符串常量有0吗
cin>>a>>b;
cout<<"area("<<r<<")="<<area(r)<<endl;
cout<<"area("<<a<<','<<b<<")="<<area(a,b)<<endl

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。