第二章_基本控制结构程序设计习题解答
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
第二章基本控制结构程序设计习题
一.基本概念与基础知识自测题
2.1 程序阅读题
2.1.1 设有说明:
int a=3, b=100;
下面的循环语句执行(1)次,执行后a、b的值分别为(2)、(3)。
while(b/a>5){
if(b-a>25) a++;
else b/=a;
}
解答:
本题检查学生整除的概念。
跟踪:
(1)14
(2)17
(3)100
2.1.2 设有说明:
int x,y,n,k;
下面程序段的功能是备选答案中的(1),当n=10,x=10打印结果是(2)。
cin>>x>>n;
k=0;
do{
x/=2;
k++;
}while(k<n);
y=1+x;
k=0;
do{
y=y*y;
k++;
}while(k<n);
cout<<y<<endl;
备选答案:
A. n n x y )1(+=
B. n n x y 2)21(+=
C. n n x y )21(+=
D. n n x y 21)2
1(++= 解答:
第一个循环使x 成为:n x 2;y 成为:n x 21+;第二个循环使y 成为:n
n x 2)2
1(+; (1)B
考虑整除,当x 连除4次2以后即为0,所以:
n
x
2为0 (2)1
2.1.3 请看如下程序段: if (num==1) cout<<”Alpha”; else if (num==2) cout<<”Bata”;
else if (num==3) cout<<”Gamma”;
else cout<<”Delta”;
当num 的值分别为1、2、3时,上面程序段的输出分别为(1) 、(2) 、(3) 。
解答:
检查条件语句与字符串输出概念: (1)Alpha (2)Bata (3)Gamma
2.1.4 执行下面程序段后,m 和k 的值分别为 (1) 、 (2) 。
int m,k;
for(k=1,m=0;k<=50;k++){
if (m>=10) break; if (m%2==0){
m+=5; continue; } m-=3; }
(1)11 (2)8
二.编程与综合练习题
2.2 有一个函数:
⎪⎩
⎪
⎨⎧≥-≤≤<=)10x ( 113x )10x (1 1-2x 1)(x x y
编写程序,输入x ,输出y 。
解:
#include <iostream> using namespace std; int main(){ double x,y; cout<<"输入x="; cin>>x; if (x<1) y=x; else if (x<10) y=2*x-1; else y=3*x-11; cout<<"y="<<y<<endl; return 0; }
2.3 设计程序将输入的百分制成绩转换为五分制输出,90分以上为5分,80~89分为4分,70~79分为3分,60~69分为2分,60分以下为1分。
解:10分一档用10进行整除获得,转换用开关语句实行。
#include <iostream> using namespace std; int main(){ int mark,result; //mark 是百分制成绩,result 是5分制 cout<<"请输入百分制成绩:"<<endl; cin>>mark; if (mark<0) { cout<<"缺考!"<<endl; return 0; } switch (mark/10){ case 9: case 10: result=5; cout<<"输出五分制成绩:"<<result<<endl; break ; case 8:
result=4;
cout<<"输出五分制成绩:"<<result<<endl;
break;
case 7:
result=3;
cout<<"输出五分制成绩:"<<result<<endl;
break;
case 6:
result=2;
cout<<"输出五分制成绩:"<<result<<endl;
break;
case 5:case 4:case 3:case 2:case 1:case 0:
result=1;
cout<<"输出五分制成绩:"<<result<<endl;
break;
default:
cout<<"输入错误!"<<endl;
}
return 0;
}
2.4 编程计算个人所得税。
个人所得税率表如下:月收入1200元起征,超过起征点500元以内部分税率5%,超过500元到2,000元部分税率10%,超过2,000元到5,000元部分税率15%,超过5,000元到20,000元部分税率20%,超过20,000元到40,000元部分税率25%,超过40,000元到60,000元部分税率30%,超过60,000元到80,000元部分税率35%,超过80,000元到100,000元部分税率40%,超过100,000元部分税率45%。
解:应该从最高税率段开始计算,分段叠加。
先算两万元以上各段,每两万为一档,采用switch 语句,注意没有使用break语句。
后面各低收入段,用if语句,也没有使用else,这两种方法是对应的。
第二要注意计算的入口处,收入减去该段的下限,进行计算,以后各段都是完整的段,计算十分简单。
#include <iostream>
using namespace std;
int main(){
double income,tax=0;
int k;
cout<<"请输入个人月收入:"<<endl;
cin>>income;
if(income<=1200){
cout<<"免征个人所得税"<<endl;
return 0;
}
else income-=1200;
if(income>20000){
k=income/20000;
switch(k){
default: tax+=(income-100000)*0.45;income=100000;
case 4: tax+=(income-80000)*0.40;income=80000;
case 3: tax+=(income-60000)*0.35;income=60000;
case 2: tax+=(income-40000)*0.30;income=40000;
case 1: tax+=(income-20000)*0.25;income=20000;
}
}
if(income>5000){
tax+=(income-5000)*0.20;
income=5000;
}
if(income>2000){
tax+=(income-2000)*0.15;
income=2000;
}
if(income>500){
tax+=(income-500)*0.10;
income=500;
}
tax+=income*0.05;
cout<<"应征所得税:"<<tax<<endl;
return 0;
}
2.5 编程打印如下图形:
*
* * *
* * * * *
* * * * * * *
* * *
* * *
* * *
解:难点在三角形左边的空格的控制,嵌套一个循环语句完成此任务。
#include <iostream>
using namespace std;
int main(){
int i,j;
for (i=1;i<=4;i++){
for(j=4-i;j>0;j--) cout<<" ";//三角形每行前部的空格
for(j=1;j<=2*i-1;j++) cout<<" *";
cout<<endl;
}
for(i=1;i<=3;i++) cout<<" * * *\n";
return 0;
}
2.6 编程输出下列图形,中间一行英文字母由输入得到。
A
B B B
C C C C C
D D D D D D D
C C C C C
B B B
A
解:分上三角和下三角两部分分别处理左边的空格。
#include <iostream>
using namespace std;
int main(){
char in;
int i,j;
do{
cout<<"输入一个字母:";
cin>>in;
if((in>=97)&&(in<=122)) in-=32;//小写改大写
}while((in<65)||(in>90));
int line=in-'A';
for (i=0;i<=line;i++){//上三角
for(j=line-i;j>0;j--) cout<<" ";//前方空格
for(j=1;j<=2*i+1;j++) cout<<' '<<char(i+'A');
cout<<endl;
}
for (i=line;i>0;i--){//下三角(少一行)
for(j=0;j<=line-i;j++) cout<<" ";
for(j=1;j<=2*i-1;j++) cout<<' '<<char(i-1+'A');
cout<<endl;
}
return 0;
}
2.7 输入n,求1!+2!+3!+…+n!
解:通常求和作为外循环,阶乘作为内循环。
这里考虑到:n!=n*(n-1)!,利用递推法运算速度大大提高,同时两者可合并为一个循环。
本程序考虑了输入的健壮性。
#include <iostream>
#include <cstdlib>
using namespace std;
int main(){
int n,i,jch=1;
double result=0; //result是结果
cout<<"请输入正整数n:"<<endl;
cin>>n;
if(n<1){
cout<<"输入错误!"<<endl;
return 1;
}
result=1;
for(i=2;i<=n;i++){
jch*=i; //jch是i的阶乘,注意n!=n*(n-1)!这样可少一层循环
result+=jch;
}
cout<<result<<endl;
return 0;
}
2.8 猴子吃桃问题:猴子摘下若干个桃子,第一天吃了桃子的一半多一个,以后每天吃了前一天剩下的一半多一个,到第十天吃以前发现只剩下一个桃子,问猴子共摘了几个桃子。
解:采用递推法。
从最后一天逆推到第一天,9次循环。
#include <iostream>
using namespace std;
const int day=10;
int main(){
int i,x=1;//最后一天只有一个
for(i=1;i<day;i++) x=(x+1)*2; //从一天前推到九天前
cout<<"开始共有桃子"<<x<<"个。
\n";
return 0;
}
2.9 从键盘输入一组非0整数,以输入0标志结束,求这组整数的平均值,并统计其中正数和负数的个数。
解:将这组整数放在整型数组中,一边输入一边求和及统计正数和负数的个数,平均数由和除以整数数量取得。
#include <fstream>
#include <iostream>
using namespace std;
int main(){
int stem[256],sum=0,pnum=0,nnum=0,i=0;
cout<<"从键盘输入一组非0整数,以输入0标志结束:"<<endl;
cin>>stem[i];
while(stem[i]!=0){
sum+=stem[i];//求和
if(stem[i]>0) pnum++;//正数数量
else nnum++;//负数数量
i++;
cin>>stem[i];
}
if(!i) cout<<"0个数"<<endl;
else {
cout<<"平均值="<<(double)sum/(pnum+nnum)<<endl;//平均值习惯不用整数
cout<<"正数个数="<<pnum<<endl;
cout<<"负数个数="<<nnum<<endl;
}
return 0;
}
2.10 编程找出1 500之中满足除以3余2,除以5余3,除以7余2的整数。
解:中国古代数学问题(韩信点兵),采用穷举法。
注意三个条件同时成立用&&。
#include <iostream>
using namespace std;
int main(){
int i;
for(i=1;i<=500;i++)
if((i%3==2)&&(i%5==3)&&(i%7==2)) cout<<i<<endl;
return 0;
}
2.11 编程求1000之内的所有完全数。
所谓完全数指的是一个数恰好等于它的所有因子和。
例如6=1+2+3,就是一个完全数。
解:采用穷举法。
两重循环,外层是从1到999依次处理,内层是求该数的所有因子的和,并判断是否等于该数。
#include <iostream>
using namespace std;
int main(){
int i,a,sum_yz; //sum_yz是a的因子和
for(a=1;a<1000;a++){
sum_yz=0;
for(i=1;i<a;i++) if (a%i==0) sum_yz+=i;
if (a==sum_yz) cout<<a<<endl;
}
return 0;
}
2.12 将100元换成用10元、5元和1元的组合,共有多少种组合方法。
解:采用穷举法。
考虑10元最多10张,5元最多20张,余下是1元。
#include <iostream>
using namespace std;
int main(){
int i,j,k,count=0;
for (i=0;i<=10;i++)//i 是10元张数,j 是5元张数,k 是1元张数 for (j=0;j<=20;j++){ k=100-10*i-5*j; if (k>=0){ cout<<i<<'\t'<<j<<'\t'<<k<<endl; count++; } } cout<<count<<endl; return 0; }
2.13 利用反正切展开计算π的近似值,要求误差10-5,公式如下:
+-+-≈7
53)(7
53x x x x x arctg
令x=1,可计算出π/4的近似值。
解:采用递推法。
初看每一项的递推通式不易写出,但每一项全看作奇数项,而偶数项全为零,则很容易写出:第1项为x ,第3项为第1项乘以x 的平方除以项序号3乘以-1,其余类推。
同时和的误差小于最后一项的绝对值。
#include <iostream> #include <cmath> using namespace std; const double e=1e-5; int main(){ double x,a,sum; int i=3; cout<<"请输入正切值:"<<endl; cin>>x; a=x; sum=x; do { a*=x*x*(-1); sum+=a/i; i+=2; }while (fabs(a/i)>e); cout<<"arctg("<<x<<")="<<sum<<endl; return 0; }
2.14 用迭代法求方程x 2+10cosx=0的根,误差限为10-5。
迭代公式如下:
n
n n n n n n x x x x x x x sin 102)cos sin (1021
-+-=
+
解:迭代法也是用循环语句实现,数学上
#include<iostream>
#include<cmath>
using namespace std;
const double e=1e-5;
int main(){
double x0,x1;
int n=0;
cout<<"输入初始近似值:"<<endl;
cin>>x1;
do{
x0=x1;
x1=(x0*x0-10*(x0*sin(x0)+cos(x0)))/(2*x0-10*sin(x0));
//x0是上次算出的结果,x1用作保存新算出的结果
n++;
} while ((fabs(x1-x0) >e)&&(n<=1e5));
if(n>1e5)
cout<<"超出迭代1e5次\n";
else cout<<"方程x*x+10*cos(x)=0的一个根为:"<<x1<<endl;
cout<<"方程误差为:"<<x1*x1+10*cos(x1)<<endl;
return 0;
}
2.15 两队选手每队5人进行一对一的比赛,甲队为A、B、C、D、E,乙队为J、K、L、M、N,经过抽签决定比赛配对名单。
规定A不和J比赛,M不和D及E比赛。
列出所有可能的比赛名单。
解:这是一个组合问题,使用穷举法。
共有5个位置,设甲队5名队员位置不变,乙队改变队员位置,进行配对。
注意第1个位置可在5个队员中任选一个,以后的位置必须扣除已选过的队员。
并扣除不能配对的情况,即得所有可能的比赛名单。
#include<iostream>
using namespace std;
int main(){
char st1[5]={'A','B','C','D','E'},st2[5]={'J','K','L','M','N'};
int i=0,j,k,l,m,n;
for(j=0;j<5;j++){//0号位
if(j==0) continue;//A不与J比赛,即st1[0]不与st2[0]比赛
for(k=0;k<5;k++){//1号位
if(k==j) continue;
for(l=0;l<5;l++){//2号位
if(l==j||l==k) continue;
for(m=0;m<5;m++){//3号位
if(m==j||m==k||m==l) continue;
if(m==3) continue;//M不与D比赛,即st1[3]不与st2[3]比赛
for(n=0;n<5;n++){//4号位
if(n==3) continue;//M不与E比赛,即st1[4]不与st2[3]比赛
if(n==j||n==k||n==l||n==m) continue;
cout<<st1[0]<<'-'<<st2[j]<<'\t'<<st1[1]<<'-'<<st2[k]<<'\t';
cout<<st1[2]<<'-'<<st2[l]<<'\t'<<st1[3]<<'-'<<st2[m]<<'\t';
cout<<st1[4]<<'-'<<st2[n]<<endl;
i++;
}
}
}
}
}
cout<<i<<endl;
return 0;
}
2.16 编程模拟选举过程。
假定四位候选人:zhang、wang、li、zhao,代号分别为1、2、3、4。
选举人直接键入候选人代号,1 4之外的整数视为弃权票,-1为终止标志。
打印各位候选人的得票以及当选者(得票数超过选票总数一半)名单。
解:用5个元素的整型数组,分别放弃权票和各候选人的得票,然后用开关语句打印。
#include<iostream>
#include<iomanip>
using namespace std;
int main(){
enum candidate{feipiao,zhang,wang,li,zhao}cand;
int vote[5]={0},i,k=0,n;
cin>>n;
while(n!=-1){
k++;
if(n>=1&&n<=4) vote[n]++;
else vote[0]++;
cin>>n;
}
for(i=0;i<5;i++){
cand=(candidate)i;
switch(cand){
case feipiao:
cout<<setw(10)<<"feipiao"<<'\t'<<vote[cand]<<endl;break;
case zhang:cout<<setw(10)<<"zhang"<<'\t'<<vote[cand];
if(vote[cand]>k/2) cout<<" 当选"<<endl;
else cout<<endl;
break;
case wang:cout<<setw(10)<<"wang"<<'\t'<<vote[cand];
if(vote[cand]>k/2) cout<<" 当选"<<endl;
else cout<<endl;
break;
case li:cout<<setw(10)<<"li"<<'\t'<<vote[cand];
if(vote[cand]>k/2) cout<<" 当选"<<endl;
else cout<<endl;
break;
case zhao:cout<<setw(10)<<"zhao"<<'\t'<<vote[cand];
if(vote[cand]>k/2) cout<<" 当选"<<endl;
else cout<<endl;
break;
}
}
return 0;
}
2.17 改造【例2.14】,将运行结果(Fibonacii数列的前20项)存入文件。
解:采用3步法。
所谓3步法,是将书上的第1和第2步合并,格式如下:首先建立或打开一个输出文件,并与磁盘文件联系:
ofstream ofile("myfile2_17.txt");
再按一定格式存入数据:ofile<<setw(15)<<fib0<<setw(15)<<fib1;等
然后关闭文件:ofile.close();
如要读出数据,则用输入文件打开,并与同一磁盘文件联系:
ifstream ifile("myfile2_17.txt");
再按同一格式读入数据:ifile>>i>>j>>k>>l;等,并输出
最后关闭文件:file.close();
#include<fstream>
#include<iostream>
#include<iomanip>
using namespace std;
const int m=20;
int main(){
int fib0=0,fib1=1,fib2,i,j,k,l,n;
char ch;
ofstream ofile("myfile2_17.txt");
ofile<<setw(15)<<fib0<<setw(15)<<fib1;
for(n=3;n<=m;n++){
fib2=fib0+fib1;
ofile<<setw(15)<<fib2;
if(n%5==0) ofile<<endl; //控制每行5个数据
fib0=fib1; fib1=fib2;
}
ofile.close();
cout<<"是否要将文件输出?Y或N"<<endl;
cin>>ch;
if(ch=='y'||ch=='Y'){
ifstream ifile("myfile2_17.txt");
while(1){
ifile>>i>>j>>k>>l>>n;//由文件读入
if(ifile.eof()!=0) break;
cout<<setw(15)<<i<<setw(15)<<j<<setw(15)<<k
<<setw(15)<<l<<setw(15)<<n<<endl;//显示
}
ifile.close();
}
return 0;
}
2.18 改造【例2.19】,将运行结果(100以内素数)存入文件。
解:采用4步法。
首先定义一个输出文件:ofstream ofile;
再打开该文件并与并与磁盘文件联系:ofile.open("myfile2_18.txt"); 按一定格式把数据存入文件。
最后关闭文件。
效果与3步法相同。
读文件同样可用3步法或4步法。
#include<fstream>
#include<iostream>
#include<iomanip>
#include<cmath>
using namespace std;
const int n=100;
int main(){
int a[n],i,j;
char ch,b[256];
ofstream ofile;
ifstream ifile;
for(i=0;i<n;i++) a[i]=1+i; //用数组保存整数1-100
a[0]=0; //1不是素数,置0
for(i=0;i<n;i++){
if(a[i]==0) continue; //该数已经置0,判断下一个数
for(j=i+1;j<n;j++) if(a[j]%a[i]==0) a[j]=0; //是a[i]倍数的元素置0;
}
ofile.open("myfile2_18.txt");
int count=0;
ofile<<"1-"<<n<<"之间的素数:"<<endl;
for(i=0;i<n;i++) //输出所有素数
if(a[i]!=0){
ofile<<setw(6)<<a[i];
count++;
if(count%10==0) ofile<<endl; //每行10个数据
}
ofile.close();
cout<<"是否要将文件输出?Y或N"<<endl;
cin>>ch;
if(ch=='y'||ch=='Y'){
ifile.open("myfile2_18.txt");
i=0;
while(ifile.get(b[i])){//不可用>>,它不能读白字符,
if(b[i]=='\n') break;
i++;
}
b[i]='\0';
cout<<b<<endl;
count=0;
while(1){
ifile>>i;//由文件读入
cout<<setw(6)<<i;//屏幕显示
count++;
if(count%10==0) cout<<endl; //每行10个数
if(ifile.eof()!=0) break;//最后一个数据后面可能没有回车,直接为文件结束}
ifile.close();
cout<<endl;
}
return 0;
}
2.19改造【例2.13】,文本由文本文件输入。
解:文本文件读入要用成员函数: ifile.get(),而不可用插入运算符<<,否则会丢失空白字符。
#include<fstream>
#include<iostream>
using namespace std;
int main(){
char ch;
int nline=0,nword=0,nch=0;
int isword=0;
ifstream ifile("ep2_19.cpp");
cout<<"读入ep2_19.cpp"<<endl;
do{
ch=ifile.get();
if(ch=='\n') nline++; //遇换行符行数+1
if(ch!=' '&&ch!='\t'&&ch!='\n'&&ch!=EOF){ //读到非间隔符
if(!isword) nword++; //在单词的起始处给单词数+1
nch++; //字符数加+1
isword=1;
}
else isword=0; //读到间隔符}while(ch!=EOF); //读到文本结束符为止ifile.close();
cout<<"行数:"<<nline<<endl;
cout<<"单词数:"<<nword<<endl;
cout<<"字符数:"<<nch<<endl;
return 0;
}。