Peter_Matthew的博客

《C程序设计(第五版)谭浩强 著》课后习题(第1-5章)

2023-10-09

本文共9.5k字,大约需要阅读48分钟。

本文所列习题答案均不含解释说明类题目。

第1章 程序设计和C语言

  1. 什么是程序?什么是程序设计?

  2. 为什么需要计算机语言?高级语言有哪些特点?

  3. 正确理解以下名词及其含义:
    (1)源程序,目标程序,可执行程序。
    (2)程序编辑,程序编译,程序连接。
    (3)程序,程序模块,程序文件。
    (4)函数,主函数,被调用函数,库函数。
    (5)程序调试,程序测试。

  4. 编写一个C程序,运行时输出
    Hello World!
    这个程序是一些国外C教材中作为第一个程序例子介绍的,一般称为Hello程序。

1
2
3
4
5
6
#include <stdio.h>
int main()
{
printf("Hello World!\n");
return 0;
}
  1. 编写一个C程序,运行时输出以下图形:
    1
    2
    3
    4
    *****
    *****
    *****
    *****
1
2
3
4
5
6
7
8
9
#include <stdio.h>
int main()
{
printf("*****\n");
printf(" *****\n");
printf(" *****\n");
printf(" *****\n");
return 0;
}
  1. 编写一个C程序,运行时输入a,b,c三个值,输出其中值最大者。
1
2
3
4
5
6
7
8
9
10
#include <stdio.h>
int main()
{
int a,b,c,max;
scanf("%d %d %d",&a,&b,&c);
max=a>b?a:b;
max=max>c?max:c;
printf("%d\n",max);
return 0;
}
  1. 看懂《C程序设计(第五版)学习辅导》第16章中介绍的用Visual Studio 2010对C程序进行编辑、编译、连接和运行的方法,并进行以下操作:
    (1)建立一个新项目,定名为project1。
    (2)建立一个新文件,定名为test1。
    (3)向test1文件输入源程序(此源程序为读者自己编写的程序)。
    (4)编译该源程序,如发现程序有误,请修改之,直到不出现“编译出错”为止。
    (5)连接并运行,得到结果。分析结果。

第2章 算法——程序的灵魂

  1. 什么是算法?试从日常生活中找3个例子,描述它们的算法。

  2. 什么叫结构化的算法?为什么要提倡结构化的算法?

  3. 试述3种基本结构的特点,请另外设计两种基本结构(要符合基本结构的特点)。

  4. 用传统流程图表示求解以下问题的算法。
    (1)有两个瓶子A和B,分别盛放醋和酱油,要求将它们互换(即A瓶原来盛醋,现改盛酱油,B瓶则相反)。
    (2)依次将10个数输入,要求输出其中最大的数。
    (3)有3个数a,b,c,要求按大小顺序把它们输出。
    (4)求1+2+3+…+100。
    (5)判断一个数n能否同时被3和5整除。
    (6)将100~200之间的素数输出。
    (7)求两个数m和n的最大公约数。
    (8)求方程式 $ax^2+bx+c=0$ 的根。分别考虑:
    ①有两个不等的实根;
    ②有两个相等的实根。

  5. 用N-S图表示第4题中各题的算法。

  6. 用伪代码表示第4题中各题的算法。

  7. 什么叫结构化程序设计?它的主要内容是什么?

  8. 用自顶向下、逐步细化的方法进行以下算法的设计:
    (1)输出1900—2000年中是闰年的年份,符合下面两个条件之一的年份是闰年:
    ①能被4整除但不能被100整除;
    ②能被100整除且能被400整除。
    (2)求 $ax^2+bx+c=0$ 的根。分别考虑 $\mathit{d}=b^2-4ac$ 大于0、等于0和小于0这3种情况。
    (3)输入10个数,输出其中最大的一个数。

第4题中各题的C程序代码如下:
(1)

1
2
3
4
5
6
7
8
9
10
#include <stdio.h>
int main()
{
int a=1,b=2,t; //假设1是醋,2是酱油。
t=a;
a=b;
b=t;
printf("A瓶内现在是%d,B瓶内现在是%d。\n",a,b);
return 0;
}

(2)

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>
int main()
{
int a,max=0,i;
for(i=0;i<10;i++)
{
scanf("%d",&a);
max=max>a?max:a;
}
printf("%d\n",max);
return 0;
}

(3)

1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>
int main()
{
int a,b,c,t;
scanf("%d %d %d",&a,&b,&c);
if(a<b){t=a;a=b;b=t;}
if(b<c){t=b;b=c;c=t;}
if(a<b){t=a;a=b;b=t;}
printf("%d %d %d\n",a,b,c);
return 0;
}

(4)

1
2
3
4
5
6
7
8
9
#include <stdio.h>
int main()
{
int i,sum=0;
for(i=1;i<=100;i++)
sum+=i;
printf("%d\n",sum);
return 0;
}

(5)

1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>
int main()
{
int n;
scanf("%d",&n);
if(n%3==0&&n%5==0)
printf("%d能同时被3和5整除。\n",n);
else
printf("%d不能同时被3和5整除。\n",n);
return 0;
}

(6)

1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>
int main()
{
int n;
scanf("%d",&n);
if(n%3==0&&n%5==0)
printf("%d能同时被3和5整除。\n",n);
else
printf("%d不能同时被3和5整除。\n",n);
return 0;
}

(7)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>
int isprime(int n)
{
int i;
for(i=2;i*i<=n;i++)
{
if(n%i==0)
return 0;
}
return 1;
}
int main()
{
int i;
for(i=100;i<=200;i++)
{
if(isprime(i))
printf("%d\n",i);
}
return 0;
}

(8)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
#include <math.h>
int main()
{
double a,b,c,x1,x2;
scanf("%lf %lf %lf",&a,&b,&c);
x1=(-b+sqrt(b*b-4*a*c))/2/a;
x2=(-b-sqrt(b*b-4*a*c))/2/a;
if(x1==x2)
printf("x1=x2=%f\n",x1);
else
printf("x1=%f\nx2=%f\n",x1,x2);
return 0;
}

第8题中各题的C程序代码如下:
(1)

1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>
int main()
{
int i;
for(i=1900;i<=2000;i++)
{
if((i%4==0&&i%100!=0)||(i%100==0&&i%400==0))
printf("%d\n",i);
}
return 0;
}

(2)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <stdio.h>
#include <math.h>
int main()
{
double a,b,c,d,x1,x2;
scanf("%lf %lf %lf",&a,&b,&c);
d=b*b-4*a*c;
if(d>0)
{
x1=(-b+sqrt(d))/2/a;
x2=(-b-sqrt(d))/2/a;
printf("x1=%f\nx2=%f\n",x1,x2);
}
else if(d==0)
{
x1=-b/2/a;
printf("x1=x2=%f\n",x1);
}
else
{
x1=-b/2/a;
x2=sqrt(-d)/2/a;
printf("无实根。\n");
printf("复数根为:x1=%f%+fi,x2=%f%+fi\n",x1,x2,x1,-x2);
}
return 0;
}

(3)

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>
int main()
{
int a,max=0,i;
for(i=0;i<10;i++)
{
scanf("%d",&a);
max=max>a?max:a;
}
printf("%d\n",max);
return 0;
}

第3章 最简单的C程序设计——顺序程序设计

  1. 假如我国国民生产总值的年增长率为7%,计算10年后我国国民生产总值与现在相比增长多少百分比。计算公式为
    $p=(1+r)^n$
    $r$ 为年增长率, $n$ 为年数, $p$ 为与现在相比的倍数。
1
2
3
4
5
6
7
8
9
#include <stdio.h>
#include <math.h>
int main()
{
double r=0.07,n=10,p;
p=pow(1+r,n);
printf("%f\n",p);
return 0;
}
  1. 存款利息的计算。有1000元,想存5年,可按以下5种办法存:
    (1)一次存5年期。
    (2)先存2年期,到期后将本息再存3年期。
    (3)先存3年期,到期后将本息再存2年期。
    (4)存1年期,到期后将本息再存一年期,连续存5次。
    (5)存活期存款。活期利息每一季度结算一次。
    2017年的银行存款利息如下:
    1年期定期存款利息为1.5%;
    2年期定期存款利息为2.1%;
    3年期定期存款利息为2.75%;
    5年期定期存款利息为3%;
    活期存款利息为0.35%(活期存款每一季度结算一次利息)。
    如果 $r$ 为年利率, $n$ 为存款年数,则计算本息和的公式如下:
    年期 本息和
    $1$ 年期本息和: $P=1000*(1+r)$ ;
    $n$ 年期本息和: $P=1000*(1+n*r)$ ;
    存 $n$ 次 $1$ 年期的本息和: $P=1000*(1+r)^n$ ;
    活期存款本息和: $P=1000*(1+\frac{r}{4})^{4n}$ 。
    说明: $1000*(1+\frac{r}{4})$ 是一个季度的本息和。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
#include <math.h>
int main()
{
double P1,P2,P3,P4,P5;
double r1=0.015,r2=0.021,r3=0.0275,r5=0.03,r0=0.0035;
P1=1000*(1+5*r5);
P2=1000*(1+2*r2)*(1+3*r3);
P3=1000*(1+3*r3)*(1+2*r2);
P4=1000*pow(1+r1,5);
P5=1000*pow(1+r0/4.0,4*5);
printf("第1种方案的本息和为%f\n",P1);
printf("第2种方案的本息和为%f\n",P2);
printf("第3种方案的本息和为%f\n",P3);
printf("第4种方案的本息和为%f\n",P4);
printf("第5种方案的本息和为%f\n",P5);
return 0;
}
  1. 购房从银行贷了一笔款 $d$ ,准备每月还款额为 $p$ ,月利率为 $r$ ,计算多少月能还清。设 $d$ 为300 000元, $p$ 为6000元, $r$ 为1%。对求得的月份取小数点后一位,对第2位按四舍五入处理。
    提示: 计算还清月数 $m$ 的公式如下:
    $m=\frac{\log{p}-\log{(p-d \times r)}}{\log{(1+r)}}$
    可以将公式改写为
    $m=\frac{\log{(\frac{p}{p-d \times r})}}{\log{(1+r)}}$
    C的库函数中有求对数的函数log10,是求以10为底的对数, $\log{(p)}$ 表示 $\log{p}$ 。
1
2
3
4
5
6
7
8
9
#include <stdio.h>
#include <math.h>
int main()
{
double d=300000,p=6000,r=0.01,m;
m=log10(p/(p-d*r))/log10(1+r);
printf("%f\n",m);
return 0;
}
  1. 分析下面的程序
    1
    2
    3
    4
    5
    6
    7
    8
    9
    #include <stdio.h>
    int main()
    { char c1,c2;
    c1=97;
    c2=98;
    printf("c1=%c,c2=%c\n",c1,c2);
    printf("c1=%d,c2=%d\n",c1,c2);
    return 0;
    }
    (1)运行时会输出什么信息?为什么?
    (2)如果将程序第4,5行改为
    1
    2
    c1=197;
    c2=198;
    运行时会输出什么信息?为什么?
    (3)如果将程序第3行改为
    1
    int c1,c2;
    运行时会输出什么信息?为什么?

(1)

1
2
c1=a,c2=b
c1=97,c2=98

第一行输出ASCII码对应的字符,第二行输出其数值。
(2)

1
2
c1=?c2=?
c1=-59,c2=-58

char是单字节的,范围为-128~127,其中ASCII码对应的有效值范围为0~127,197和198超过了这个范围,赋给char时按位截断赋值,其对应的二进制码分别为11000101和11000110,取8位反码表示对应的数值为-59和-58。
第一行,对于超出ASCII码范围的值其最高位为1,屏幕会将其和下一个字符连在一起表示,同时该字符是未知的。
第二行,输出了其数值。
(3)

1
2
c1=a,c2=b
c1=97,c2=98

由于int范围大于char,所以不会出现精度损失。

1
2
c1=?c2=?
c1=197,c2=198

第一行,对于超出ASCII码范围的值其最高位为1,屏幕会将其和下一个字符连在一起表示,同时该字符是未知的。
第二行,输出了其数值。

  1. 用下面的scanf函数输入数据,使a=3,b=7,x=8.5,y=71.82,c1=’A’,c2=’a’。在键盘上应如何输入?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #include <stdio.h>
    int main()
    {
    int a,b;
    float x,y;
    char c1,c2;
    scanf("a=%db=%d",&a,&b);
    scanf("%f%e",&x,&y);
    scanf("%c%c",&c1,&c2);
    return 0;
    }
1
2
a=3b=7
8.5 71.82Aa
  1. 请编程序将“China”译成密码,密码规律是:用原来的字母后面第4个字母代替原来的字母。例如,字母“A”后面第4个字母是“E”,用“E”代替“A”。因此,“China”应译为“Glmre”。请编一程序,用赋初值的方法使c1,c2,c3,c4,c5这五个变量的值分别为’C’,’h’,’i’,’n’,’a’,经过运算,使c1,c2,c3,c4,c5分别变为’G’,’l’,’m’,’r’,’e’。分别用putchar函数和printf函数输出这5个字符。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
int main()
{
char c1='C',c2='h',c3='i',c4='n',c5='a';
c1+=4;
c2+=4;
c3+=4;
c4+=4;
c5+=4;
printf("%c%c%c%c%c\n",c1,c2,c3,c4,c5);
putchar(c1);
putchar(c2);
putchar(c3);
putchar(c4);
putchar(c5);
putchar('\n');
return 0;
}
  1. 设圆半径 $r=1.5$ ,圆柱高 $h=3$ ,求圆周长、圆面积、圆球表面积、圆球体积、圆柱体积。用scanf输入数据,输出计算结果,输出时要求有文字说明,取小数点后2位数字。请编函数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
#define PI 3.1415926
int main()
{
double c,s,sq,vq,vz,r=1.5,h=3;
c=2*PI*r;
s=PI*r*r;
sq=4*PI*r*r;
vq=4.0/3.0*PI*r*r*r;
vz=s*h;
printf("c=%.2f\n",c);
printf("s=%.2f\n",s);
printf("sq=%.2f\n",sq);
printf("vq=%.2f\n",vq);
printf("vz=%.2f\n",vz);
return 0;
}
  1. 编程序,用getchar函数读入两个字符给c1和c2,然后分别用putchar函数和printf函数输出这两个字符。思考以下问题:
    (1)变量c1和c2应定义为字符型、整型还是二者皆可?
    (2)要求输出c1和c2值得ASCII码,应如何处理?用putchar函数还是printf函数?
    (3)整型变量与字符变量是否在任何情况下都可以互相代替?如:
    1
    char c1,c2;
    1
    int c1,c2;
    是否无条件地等价?
1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>
int main()
{
char c1,c2;
c1=getchar();
c2=getchar();
putchar(c1);
putchar(c2);
putchar('\n');
printf("%c%c\n",c1,c2);
return 0;
}

(1)二者皆可。
(2)printf函数:

1
printf("%d%d\n",c1,c2);

(3)在ASCII码的范围(0~127)内,可以,一旦超出就不可。

第4章 选择结构程序设计

  1. 什么是算术运算?什么是关系运算?什么是逻辑运算?

算术运算:+ - * /
关系运算:== != < > <= >=
逻辑运算:|| && !

  1. C语言中如何表示“真”和“假”?系统如何判断一个量的“真”和“假”?

逻辑表达式中,1为真,0为假。系统内部将0视作假,非0视作真。

  1. 写出下面各逻辑表达式的值,设a=3,b=4,c=5。
    (1)a+b>c&&b==c
    (2)a||b+c&&b-c
    (3)!(a>b)&&!c||1
    (4)!(x=a)&&(y=b)&&0
    (5)!(a+b)+c-1&&b+c/2

(1)0
(2)1
(3)1
(4)0
(5)1

  1. 有3个整数a,b,c由键盘输入,输出其中最大的数。
1
2
3
4
5
6
7
8
9
10
#include <stdio.h>
int main()
{
int a,b,c,max;
scanf("%d %d %d",&a,&b,&c);
max=a>b?a:b;
max=max>c?max:c;
printf("%d\n",max);
return 0;
}
  1. 从键盘输入一个小于1000的正数,要求输出它的平方根(如平方根不是整数,则输出其整数部分)。要求在输入数据后先对其进行检查是否为小于1000的正数。若不是,则要求重新输入。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>
#include <math.h>
int main()
{
int n,m;
printf("Input a positive number less than 1000:");
scanf("%d",&n);
while(n<=0||n>=1000)
{
printf("Input Error! Input a positive number less than 1000:");
scanf("%d",&n);
}
m=(int)sqrt(n);
printf("The square root is %d\n",m);
return 0;
}
  1. 有一个函数:
    Book-Exercises-of-PLC-5th-THQ-4-6-1
    写程序,输入 $x$ 的值,输出 $y$ 相应的值。
1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>
int main()
{
double x,y;
scanf("%lf",&x);
if(x<1)y=x;
else if(x<10)y=2*x-1;
else y=3*x-11;
printf("%f\n",y);
return 0;
}
  1. 有一函数:
    Book-Exercises-of-PLC-5th-THQ-4-7-1
    有人编写了以下两个程序,请分析它们是否能实现题目要求。不要急于上机运行程序,先分析两个程序的逻辑,画出它们的流程图,分析它们的运行情况。然后上机运行程序,观察和分析结果。
    (1)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    #include <stdio.h>
    int main()
    {
    int x,y;
    printf("enter x:");
    scanf("%d",&x);
    y=-1;
    if(x!=0)
    if(x>0)
    y=1;
    else
    y=0;
    printf("x=%d,y=%d\n",x,y);
    return 0;
    }
    (2)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #include <stdio.h>
    int main()
    {
    int x,y;
    printf("enter x:");
    scanf("%d",&x);
    y=0;
    if(x>=0)
    if(x>0) y=1;
    else y=-1;
    printf("x=%d,y=%d\n",x,y);
    return 0;
    }

均不行。else总是向上找离它最近的if配对,因此(1)和(2)的函数实际如下:
Book-Exercises-of-PLC-5th-THQ-4-7-2
事实上,如果加上一个代码段括号{},就可以正常,修改如下:
(1)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
int main()
{
int x,y;
printf("enter x:");
scanf("%d",&x);
y=-1;
if(x!=0)
{
if(x>0)
y=1;
}
else
y=0;
printf("x=%d,y=%d\n",x,y);
return 0;
}

(2)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
int main()
{
int x,y;
printf("enter x:");
scanf("%d",&x);
y=0;
if(x>=0)
{
if(x>0) y=1;
}
else y=-1;
printf("x=%d,y=%d\n",x,y);
return 0;
}
  1. 给出一百分制成绩,要求输出成绩等级’A’、’B’、’C’、’D’、’E’。90分以上为’A’,80~89分为’B’,70~79分为’C’,60~69分为’D’,60分以下为’E’。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>
int main()
{
int x;
scanf("%d",&x);
switch(x/10)
{
case 10:
case 9:printf("A\n");break;
case 8:printf("B\n");break;
case 7:printf("C\n");break;
case 6:printf("D\n");break;
default:printf("E\n");break;
}
return 0;
}
  1. 给出一个不多于5位的正整数,要求:
    ①求出它是几位数;
    ②分别输出每一位数字;
    ③按逆序输出各位数字,例如原数为321,应输出123。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <stdio.h>
int main()
{
int x,a,b,c,d,e;
scanf("%d",&x);
a=x/10000;
b=x/1000%10;
c=x/100%10;
d=x/10%10;
e=x%10;
if(a)
{
printf("五位数\n");
printf("%d %d %d %d %d\n",a,b,c,d,e);
printf("%d%d%d%d%d\n",e,d,c,b,a);
}
else if(b)
{
printf("四位数\n");
printf("%d %d %d %d\n",b,c,d,e);
printf("%d%d%d%d\n",e,d,c,b);
}
else if(c)
{
printf("三位数\n");
printf("%d %d %d\n",c,d,e);
printf("%d%d%d\n",e,d,c);
}
else if(d)
{
printf("两位数\n");
printf("%d %d\n",d,e);
printf("%d%d\n",e,d);
}
else
{
printf("一位数\n");
printf("%d\n",e);
printf("%d\n",e);
}
return 0;
}
  1. 企业发放的奖金根据利润提成。利润 $I$ 低于或等于 100 000 元的,奖金可提成10%;利润高于100 000元,低于200 000元(100 000 $< I \leq$ 200 000)时,低于100 000元的部分按10%提成,高于100 000元的部分,可提成7.5%;200 000 $< I \leq$ 400 000时,低于200 000元的部分仍按上述办法提成(下同)。高于200 000元的部分按5%提成;400 000 $< I \leq$ 600 000元时,高于400 000元的部分按3%提成;600 000 $< I \leq$ 1 000 000时,高于600 000元的部分按1.5%提成; $I >$ 1 000 000时,超过1 000 000元的部分按1%提成。从键盘输入当月利润 $I$ ,求应发奖金总数。
    要求:
    (1)用if语句编程序;
    (2)用switch语句编程序。

(1)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <stdio.h>
int main()
{
double i,sum=0;
scanf("%lf",&i);
if(i>1000000)
{
sum+=(i-1000000)*0.01;
i=1000000;
}
if(i>600000)
{
sum+=(i-600000)*0.015;
i=600000;
}
if(i>400000)
{
sum+=(i-400000)*0.03;
i=400000;
}
if(i>200000)
{
sum+=(i-200000)*0.05;
i=200000;
}
if(i>100000)
{
sum+=(i-100000)*0.075;
i=100000;
}
sum+=i*0.1;
printf("%f\n",sum);
return 0;
}

(2)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h>
int main()
{
double i,sum=0;
scanf("%lf",&i);
switch(((int)i-1)/100000)
{
default:sum+=(i-1000000)*0.01;i=1000000;
case 9:
case 8:
case 7:
case 6:sum+=(i-600000)*0.015;i=600000;
case 5:
case 4:sum+=(i-400000)*0.03;i=400000;
case 3:
case 2:sum+=(i-200000)*0.05;i=200000;
case 1:sum+=(i-100000)*0.075;i=100000;
case 0:sum+=i*0.1;break;
}
printf("%f\n",sum);
return 0;
}
  1. 输入4个整数,要求按由小到大的顺序输出。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
int main()
{
int a,b,c,d,t;
scanf("%d %d %d %d",&a,&b,&c,&d);
if(a<b){t=a;a=b;b=t;}
if(b<c){t=b;b=c;c=t;}
if(c<d){t=c;c=d;d=t;}
if(a<b){t=a;a=b;b=t;}
if(b<c){t=b;b=c;c=t;}
if(a<b){t=a;a=b;b=t;}
printf("%d %d %d %d\n",a,b,c,d);
return 0;
}
  1. 有4个圆塔,圆心分别为(2,2)、(-2,2)、(-2,-2)、(2,-2),圆半径为1,见图。这4个塔的高度为10m,塔以外无建筑物。今输入任意一点的坐标,求该点的建筑高度(塔外的高度为零)。
    Book-Exercises-of-PLC-5th-THQ-4-12-1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
#include <math.h>
int main()
{
int h;
double d1,d2,d3,d4,x,y;
scanf("%lf %lf",&x,&y);
d1=sqrt(pow(x-2,2)+pow(y-2,2));
d2=sqrt(pow(x+2,2)+pow(y-2,2));
d3=sqrt(pow(x+2,2)+pow(y+2,2));
d4=sqrt(pow(x-2,2)+pow(y+2,2));
if(d1<=1||d2<=1||d3<=1||d4<=1)
h=10;
else
h=0;
printf("%d\n",h);
return 0;
}

第5章 循环结构程序设计

  1. 请画出例5.6中给出的3个程序段的流程图。

  2. 请补充例5.7程序,分别统计当“fabs(t)>=1e-6”和“fabs(t)>=1e-8”时执行循环体的次数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>
#include <math.h>
int main()
{
int sign=1,times=0;
double pi=0.0,n=1.0,term=1.0;

while(fabs(term)>=1e-6)
{
times++;
pi=pi+term;
n=n+2;
sign=-sign;
term=sign/n;
}
pi=pi*4;
printf("pi=%10.8f\n",pi);
printf("times:%d\n",times);
return 0;
}

“fabs(t)>=1e-6”时执行循环体500000次。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>
#include <math.h>
int main()
{
int sign=1,times=0;
double pi=0.0,n=1.0,term=1.0;

while(fabs(term)>=1e-8)
{
times++;
pi=pi+term;
n=n+2;
sign=-sign;
term=sign/n;
}
pi=pi*4;
printf("pi=%10.8f\n",pi);
printf("times:%d\n",times);
return 0;
}

“fabs(t)>=1e-8”时执行循环体50000000次。

  1. 输入两个正整数m和n,求其最大公约数和最小公倍数。

辗转相除法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>
int main()
{
int m,n,t,gcd,lcm;
scanf("%d %d",&m,&n);
lcm=m*n;
while(n!=0)
{
m%=n;
t=m;m=n;n=t;
}
gcd=m;
lcm/=m;
printf("gcd=%d,lcm=%d\n",gcd,lcm);
return 0;
}

更相减损法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>
int main()
{
int m,n,gcd,lcm;
scanf("%d %d",&m,&n);
lcm=m*n;
while(m!=n)
{
if(m<n)n-=m;
if(m>n)m-=n;
}
gcd=m;
lcm/=m;
printf("gcd=%d,lcm=%d\n",gcd,lcm);
return 0;
}
  1. 输入一行字符,分别统计出其中英文字母、空格、数字和其他字符的个数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>
int main()
{
int i,zm=0,kg=0,sz=0,qt=0;
char s[100];
gets(s);
for(i=0;s[i]!='\0';i++)
{
if(s[i]>='a'&&s[i]<='z'||s[i]>='A'&&s[i]<='Z')
zm++;
else if(s[i]==' ')
kg++;
else if(s[i]>='0'&&s[i]<='9')
sz++;
else
qt++;
}
printf("zm=%d,kg=%d,sz=%d,qt=%d\n",zm,kg,sz,qt);
return 0;
}
  1. 求 $S_n=a+aa+aaa+\cdots+\overset{n个a}{aa \cdots a}$ 之值,其中 $a$ 是一个数字, $n$ 表示 $a$ 的位数, $n$ 由键盘输入。例如:
    2+22+222+2222+22222 (此时 $n=$ 5)
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
int main()
{
int a,n,Si=0,Sn=0,i;
scanf("%d %d",&a,&n);
for(i=0;i<n;i++)
{
Si=Si*10+a;
Sn+=Si;
}
printf("%d\n",Sn);
return 0;
}
  1. 求 $\sum_{n=1}^{20}n!$ (即求 $1!+2!+3!+4!+\cdots+20!$ )
1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>
int main()
{
long long i,Sn=0,Si=1;
for(i=1;i<=20;i++)
{
Si*=i;
Sn+=Si;
}
printf("%lld\n",Sn);
return 0;
}
  1. 求 $\sum_{k=1}^{100}k+\sum_{k=1}^{50}k^2+\sum_{k=1}^{10}\frac{1}{k}$ 。
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
int main()
{
double i,Sn=0;
for(i=1;i<=100;i++)
Sn+=i;
for(i=1;i<=50;i++)
Sn+=i*i;
for(i=1;i<=10;i++)
Sn+=1.0/i;
printf("%f\n",Sn);
return 0;
}
  1. 输出所有的“水仙花数”,所谓“水仙花数”是指一个3位数,其各位数字立方和等于该数本身。例如, $153$ 是水仙花数,因为 $153=1^3+5^3+3^3$ 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
int main()
{
int i,a,b,c;
for(i=100;i<1000;i++)
{
a=i/100;
b=i/10%10;
c=i%10;
if(i==a*a*a+b*b*b+c*c*c)
printf("%d\n",i);
}
return 0;
}
  1. 一个数如果恰好等于它的因子之和,这个数就称为“完数”。例如,6的因子为1,2,3,而6=1+2+3,因此6是“完数”。编程序找出1000之内的所有完数,并按下面格式输出其因子:
    1
    6 its factors are 1,2,3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <stdio.h>
int main()
{
int i,j,s;
for(i=1;i<=1000;i++)
{
s=0;
for(j=1;j<i;j++)
{
if(i%j==0)
s+=j;
}
if(s==i)
{
printf("%d its factors are 1",i);
for(j=2;j<i;j++)
{
if(i%j==0)
printf(",%d",j);
}
printf("\n");
}
}
return 0;
}
  1. 有一个分数序列
    $\frac{2}{1},\frac{3}{2},\frac{5}{3},\frac{8}{5},\frac{13}{8},\frac{21}{8},\cdots$
    求出这个数列的前20项之和。

分母是斐波那契数列,分子是斐波那契数列中分母的下一项数字。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
int main()
{
double fm=1,fz=2,t,Sn=0;
int i;
for(i=0;i<20;i++)
{
Sn+=fz/fm;
t=fm;
fm=fz;
fz+=t;
}
printf("%f\n",Sn);
return 0;
}
  1. 一个球从100m高度自由落下,每次落地后反弹回原高度的一半,再落下,再反弹。求它在第10次落地时共经过多少米,第10次反弹多高。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
int main()
{
double h=100,s=100;
int i;
for(i=1;i<10;i++)
{
h/=2;
s+=2*h;
}
h/=2;
printf("s=%f,h=%f\n",s,h);
return 0;
}
  1. 猴子吃桃问题。猴子第1填摘下若干个桃子,当即吃了一半,还不过瘾,又多吃了一个。第2天早上又将剩下的桃子吃掉一半,又多吃了一个。以后每天早上都吃了前一天剩下的一半零一个。到第10天早上想再吃时,就只剩一个桃子了。求第1天共摘多少个桃子。
1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>
int main()
{
int i,s=1;
for(i=9;i>=1;i--)
{
s=(s+1)*2;
}
printf("%d\n",s);
return 0;
}
  1. 用迭代法求 $x=\sqrt{a}$ 。求平方根的迭代公式为
    $x_{n+1}=\frac{1}{2}(x_n+\frac{a}{x_n})$
    要求前后两次求出的 $x$ 的差的绝对值小于 $10^{-5}$ 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>
#include <math.h>
int main()
{
double a,x,x1;
scanf("%lf",&a);
x=x1=a;
do
{
x=x1;
x1=(x+a/x)/2;
}while(fabs(x-x1)>=1e-5);
x=x1;
printf("%f\n",x);
return 0;
}
  1. 用牛顿迭代法求下面方程在1.5附近的根:
    $2x^3-4x^2+3x-6=0$

牛顿迭代法(牛顿切线法)假设一个接近根的值 $x_0$ 求出 $f(x_0)$ ,过该点作切线,交 $x$ 轴于 $(x_1,0)$ ,用 $x_1$ 代替 $x_0$ 重复操作,最后得到的值会慢慢接近真正的根 $x^*$ 。
由 $f’(x_0)=\frac{f(x_0)}{x_0-x_1}$ ,得 $x_1=x_0-\frac{f(x_0)}{f’(x_0)}$ 。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>
#include <math.h>
int main()
{
double x0=1.5,x1=1.5,f,f_;
do
{
x0=x1;
f=((2*x0-4)*x0+3)*x0-6;
f_=(6*x0-8)*x0+3;
x1=x0-f/f_;
}while(fabs(x1-x0)>=1e-5);
x0=x1;
printf("%f\n",x0);
return 0;
}
  1. 用二分法求下面方程在 $(-10,10)$ 的根:
    $2x^3-4x^2+3x-6=0$
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <stdio.h>
#include <math.h>
int main()
{
double l=-10,r=10,mid,fl=-2436,fr=1624,fmid;
do
{
mid=(l+r)/2;
fmid=((2*mid-4)*mid+3)*mid-6;
if(fmid*fl<0)
{
r=mid;
fr=fmid;
}
else
{
l=mid;
fl=fmid;
}
}while(fabs(l-r)>=1e-5);
printf("%f\n",mid);
return 0;
}
  1. 输出以下图案:
    1
    2
    3
    4
    5
    6
    7
       *
    ***
    *****
    *******
    *****
    ***
    *
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h>
int main()
{
int i,j;
for(i=0;i<4;i++)
{
for(j=0;j<3-i;j++)
printf(" ");
for(j=0;j<2*i+1;j++)
printf("*");
printf("\n");
}
for(i=2;i>=0;i--)
{
for(j=0;j<3-i;j++)
printf(" ");
for(j=0;j<2*i+1;j++)
printf("*");
printf("\n");
}
return 0;
}
  1. 两个乒乓球队进行比赛,各出3人。甲队为A,B,C 3人,乙队为X,Y,Z 3人。已抽签决定比赛名单。有人向队员打听比赛的名单,A所他不和X比,C所他不和X,Z比,请编程序找出3对赛手的名单。
1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>
int main()
{
char A,B,C,X='X',Y='Y',Z='Z';
for(A=X;A<=Z;A++)
for(B=X;B<=Z;B++)
for(C=X;C<=Z;C++)
if(A!=B&&B!=C&&A!=C)
if(A!=X&&C!=X&&C!=Z)
printf("A-%c B-%c C-%c\n",A,B,C);
return 0;
}

注:本章习题13~15所用的方法,可参考《C程序设计(第五版)学习辅导》第5章习题解答中的介绍。

第6章 利用数组处理批量数据

  1. 用筛选法求100之内的素数。

①先把1挖掉;
②把2标记为素数,将2的其他倍数挖掉;
③把3标记为素数,将3的其他倍数挖掉;
④4被挖掉,跳过;
⑤……

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>
int main()
{
int notprime[105]={0},i,j;
notprime[1]=1;
for(i=2;i<=100;i++)
{
if(!notprime[i])
{
printf("%d\n",i);
for(j=2;i*j<=100;j++)
notprime[i*j]=1;
}
}
return 0;
}
  1. 用选择法对10个整数排序。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <stdio.h>
int main()
{
int a[10],i,j,t,min;
for(i=0;i<10;i++)
scanf("%d",&a[i]);
for(i=0;i<9;i++)
{
min=i;
for(j=i+1;j<10;j++)
{
if(a[j]<a[min])
min=j;
}
t=a[i];
a[i]=a[min];
a[min]=t;
}
for(i=0;i<10;i++)
printf("%d ",a[i]);
printf("\n");
return 0;
}
  1. 求一个 $3 \times 3$ 的整型矩阵对角线元素之和。
1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>
int main()
{
int a[3][3],i,j,s=0;
for(i=0;i<3;i++)
for(j=0;j<3;j++)
scanf("%d",&a[i][j]);
for(i=0;i<3;i++)
s+=a[i][i];
printf("%d\n",s);
return 0;
}
  1. 有一个已排好序的数组,要求输入一个数后,按原来排序的规律将它插入数组中。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>
int main()
{
int a[11],b,i,pos;
for(i=0;i<10;i++)
scanf("%d",&a[i]);
scanf("%d",&b);
for(i=0;i<10;i++)
if(b<a[i])
break;
pos=i;
for(i=10;i>pos;i--)
a[i]=a[i-1];
a[pos]=b;
for(i=0;i<=10;i++)
printf("%d ",a[i]);
printf("\n");
return 0;
}
  1. 将一个数组中的值按逆序重新存放。例如,原来顺序为8,6,5,4,1。要求改为1,4,5,6,8。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
int main()
{
int a[5],i,t;
for(i=0;i<5;i++)
scanf("%d",&a[i]);
for(i=0;i<5/2;i++)
{
t=a[i];
a[i]=a[4-i];
a[4-i]=t;
}
for(i=0;i<5;i++)
printf("%d ",a[i]);
printf("\n");
return 0;
}
  1. 输出以下的杨辉三角形(要求输出10行)。
    1
    1 1
    1 2 1
    1 3 3 1
    1 4 6 4 1
    1 5 10 10 5 1
    $\vdots$ $\vdots$ $\vdots$ $\vdots$ $\vdots$ $\vdots$
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
int main()
{
int a[10][10],i,j;
for(i=0;i<10;i++)
a[i][0]=a[i][i]=1;
for(i=2;i<10;i++)
for(j=1;j<i;j++)
a[i][j]=a[i-1][j-1]+a[i-1][j];
for(i=0;i<10;i++)
{
for(j=0;j<=i;j++)
printf("%d ",a[i][j]);
printf("\n");
}
return 0;
}
  1. 输出“魔方阵”。所谓魔方阵是指这样的方阵,它的每一行、每一列和对角线之和均相等。例如,三阶魔方阵为
    8 1 6
    3 5 7
    4 9 2
    要求输出 1 ~ $n^2$ 的自然数构成的魔方阵。

奇数阶魔方阵的生成规律如下:
① $1$ 位于第 $1$ 行第 $\frac{n+1}{2}$ 列;
② $2$ 到 $n^2$ 的各数,每一个数存放的行比前一个数少 $1$ ,若前一个数已放在第 $1$ 行,则这一个放在第 $n$ 行;
③ $2$ 到 $n^2$ 的各数,每一个数存放的列比前一个数多 $1$ ,若前一个数已放在第 $n$ 列,则这一个放在第 $1$ 列;
④ 若当前数要放的位置已经有数,则存放到前一个数同一列的下一行的位置,若前一个数已放在第 $n$ 行,则这一个放在第 $1$ 行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <stdio.h>
int main()
{
int a[11][11],i,j,k,n;
scanf("%d",&n);
if(n%2==0)
{
printf("Only Odd Number!\n");
return 0;
}
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
a[i][j]=0;
i=1;
j=(n+1)/2;
a[i][j]=1;
for(k=2;k<=n*n;k++)
{
if(i==1)i=n;
else i--;
if(j==n)j=1;
else j++;
if(a[i][j])
{
if(i==n)i=1;
else i++;
if(j==1)j=n;
else j--;

if(i==n)i=1;
else i++;
}
a[i][j]=k;
}
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
printf("%2d ",a[i][j]);
printf("\n");
}
return 0;
}
  1. 找出一个二维数组中的鞍点,即该位置上的元素在该行上最大、在该列上最小。也可能没有鞍点。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <stdio.h>
int main()
{
int a[5][5],i,j,max,flag,num=0;
for(i=0;i<5;i++)
for(j=0;j<5;j++)
scanf("%d",&a[i][j]);
for(i=0;i<5;i++)
{
max=0;
flag=1;
for(j=0;j<5;j++)
max=a[i][max]<a[i][j]?j:max;
for(j=0;j<5;j++)
if(a[i][max]>a[j][max])
{
flag=0;
break;
}
if(flag)
{
printf("a[%d][%d]=%d\n",i,max,a[i][max]);
num++;
}
}
if(!num)
printf("It does not exist!\n");
return 0;
}
  1. 有15个数按由大到小顺序存放在一个数组中,输入一个数,要求用折半查找法找出该数是数组中第几个元素的值。如果该数不在数组中,则输出“无此数”。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <stdio.h>
int main()
{
int a[15],b,i,l=0,r=14,mid;
for(i=0;i<15;i++)
scanf("%d",&a[i]);
scanf("%d",&b);
while(l<r)
{
mid=(l+r)/2;
if(a[mid]>b)
l=mid+1;
else if(a[mid]<b)
r=mid-1;
else
{
l=r=mid;
break;
}
}
if(a[l]==b)
printf("a[%d]=%d\n",l,b);
else
printf("No Found!\n");
return 0;
}
  1. 有一篇文章,共有3行文字,每行有80个字符。要求分别统计出其中英文大写字母、小写字母、数字、空格以及其它字符的个数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <stdio.h>
int main()
{
int i,j,dx=0,xx=0,sz=0,kg=0,qt=0;
char s[3][81];
for(i=0;i<3;i++)
{
gets(s[i]);
for(j=0;s[i][j]!='\0';j++)
{
if(s[i][j]>='A'&&s[i][j]<='Z')
dx++;
else if(s[i][j]>='a'&&s[i][j]<='z')
xx++;
else if(s[i][j]==' ')
kg++;
else if(s[i][j]>='0'&&s[i][j]<='9')
sz++;
else
qt++;
}
}
printf("dx=%d,xx=%d,sz=%d,kg=%d,qt=%d\n",dx,xx,sz,kg,qt);
return 0;
}
  1. 输出以下图案:
    1
    2
    3
    4
    5
    * * * * *
    * * * * *
    * * * * *
    * * * * *
    * * * * *
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
int main()
{
int i,j;
for(i=0;i<5;i++)
{
for(j=0;j<i;j++)
printf(" ");
for(j=0;j<5;j++)
printf("* ");
printf("\n");
}
return 0;
}
  1. 有一行电文,已按下面规律译成密码:
    A→Z a→z
    B→Y b→y
    C→X C→x
    $\; \; \vdots \; \; \; \; \; \vdots$
    即第1个字母变成第26个字母,第i个字母变成第(26-i+1)个字母,非字母字符不变。要求编程序将密码译回原文,并输出密码和原文。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
int main()
{
int i;
char s[100];
gets(s);
printf("%s\n",s);
for(i=0;s[i]!='\0';i++)
{
if(s[i]>='A'&&s[i]<='Z')
s[i]=25-(s[i]-'A')+'A';
if(s[i]>='a'&&s[i]<='z')
s[i]=25-(s[i]-'a')+'a';
}
printf("%s\n",s);
return 0;
}
  1. 编一程序,将两个字符串连接起来,不要用strcat函数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
int main()
{
int i,j;
char s1[200],s2[100];
gets(s1);
gets(s2);
for(i=0;s1[i]!='\0';i++);
for(j=0;s2[j]!='\0';i++,j++)
s1[i]=s2[j];
s1[i]='\0';
printf("%s\n",s1);
return 0;
}
  1. 编一个程序,将两个字符串s1和s2比较,若s1>s2,输出一个正数;若s1=s2,输出0;若s1<s2,输出一个负数。不要用strcpy函数。两个字符串用gets函数读入。输出的正数或负数的绝对值应是相比较的两个字符串相应字符的ASCII码的差值。例如,”A”与”C”相比,由于”A”<”C”,应输出负数,同时由于’A’与’C’的ASCII码差值为2,因此应输出“-2”。同理:”And”和”Aid”比较,根据第2个字符比较结果,”n”比”i”大5,因此应输出“5”。
1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>
int main()
{
int i;
char s1[200],s2[100];
gets(s1);
gets(s2);
for(i=0;s1[i]==s2[i]&&s1[i]!='\0';i++);
printf("%d\n",s1[i]-s2[i]);
return 0;
}
  1. 编写一个程序,将字符数组s2中的全部字符复制到字符数组s1中。不用strcpy函数。复制时,’\0’也要复制过去。’\0’后面的字符不复制。
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
int main()
{
int i;
char s1[200],s2[100];
gets(s1);
gets(s2);
for(i=0;s2[i]!='\0';i++)
s1[i]=s2[i];
s1[i]='\0';
printf("%s\n",s1);
return 0;
}

知识共享许可协议

知识共享许可协议

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。

使用支付宝打赏
使用微信打赏

若你觉得我的文章对你有帮助,欢迎点击上方按钮对我打赏