C语言程序设计(第五版)谭浩强著 第5章习题答案

1.

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

解题思路:

设置一个整型变量count,初值为0;循环体每执行一次后,count的值加一。

(1)当”fabs(t)=1e-6“时

代码:

#include<stdio.h>
#include<math.h>
int main() {
    int count = 0;                            //count用来记录循环体执行的次数
    int sign = 1;                            //sign用来表示数值的符号
    double pi = 0.0, n = 1.0, term = 1.0;    //n代表分母,term代表当前项的值
    while (fabs(term) > 1e-6) {
        pi = pi + term;
        n = n + 2;
        sign *= -1;
        term = sign / n;
        count++;
    }
    pi *= 4;
    printf("pi=%10.8f\n", pi);
    printf("循环体执行了%d次\n", count);
    return 0;
}

运行结果:

(2)当”fabs(t)=1e-8“时

运行结果:

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

解题思路:

  • 最大公约数:利用辗转相除法(以除数和余数反复做除法运算,当余数为 0 时,取当前算式除数为最大公约数)

例如求2344和766的最大公约数,过程如下:

2344/766=3---余46
766/46=16---余30
46/30=1---余16
30/16=1---余14
16/14=1---余2
14/2=7---余0
当余数为0时,除数为2,因此2344和766的最大公约数为2.
  • 最小公倍数:利用公式法(两个数的乘积 等于 两个数最大公约数和最小公倍数的乘积),最小公倍数等于两个数的乘积除以两个数的最大公约数。

代码:

#include<stdio.h>
int main() {
    int m, n, t, mul, ret;                    //mul记录两个数的乘积,ret记录余数
    printf("请输入两个正整数:");
    scanf_s("%d%d", &m, &n);
    //保证m大于
    mul= m * n;
    if (m < n) {
        t = m;
        m = n;
        n = t;
    }
    //
    while (ret = m % n) {                   //若余数不为0,执行循环体内容;
        m = n;
        n = ret;
    }
    printf("最大公约数为:%d\n最小公倍数为:%d\n", n, mul / n);
    return 0;
}

运行结果:

4.输入一行字符,分别统计出其中英文字母、空格、数字和其他字符的个数。

解题思路:

用while循环和 getchar()函数,每次从键盘读入一个字符,直到读入'\n'为止;读入字符后,依次判断其是否为字母、空格、数字、其他,若是,则相应记录加一。

代码:

#include<stdio.h>
int main() {
    char c;
    int n1=0, n2=0, n3=0, n4=0;                //n1记录英文字母个数;n2记录空格个数;n3记录数字个数;n4记录其他字符个数
    while ((c = getchar()) != '\n') {
        if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'))
            n1++;
        else if (c == ' ')
            n2++;
        else if (c >= '1' && c <= '9')
            n3++;
        else
            n4++;
    }
    printf("英文字母个数为:%d\n", n1);
    printf("空格个数为:%d\n", n2);
    printf("空格个数为:%d\n", n3);
    printf("其他字符个数为:%d\n", n4);
    return 0;
}

运行结果:

5.求Sn=a+aa+aaa+...+aa...a之值,其中a是一个数字,n代表a的位数,例如:2+22+222+2222+22222(此时n=5)

解题思路:

Sn由n项相加组成,因此考虑由循环;假设a=2,n=5,分析各项组成可得如下规律:

当前项的值=前一项的值+a*10^n

代码:

#include<stdio.h>
#include<math.h>
int main() {
    int a, n, cur_val=0, Sn=0;         //cur_val记录当前项的值
    printf("请分别输入a和n的值:");
    scanf_s("%d%d", &a, &n);
    for (int i = 0; i < n; i++) {      //注:第n项i的值为(n-1),因此for循环中用i<n
        cur_val +=a*pow(10, i);
        Sn += cur_val;
    }
    printf("%d", Sn);
    return 0;
}

运行结果:

6.求(即求1!+2!+3!+4!+...+20!)。

解题思路:

法一:类似于第五题,不再赘述。

法二:利用嵌套循环,大循环从1到20,控制加数个数;内层求解阶乘。

注:显然结果已经超过int类型所能表示的范围,因此应使用double类型。

代码:

//法一:
#include<stdio.h>
#include<math.h>
int main() {
    double cur=1, total=0;
    for (int i = 1; i <= 20; i++) {
        cur = cur * i;
        total = total + cur;
    }
    printf("%lf", total);
    return 0;
}

//法二:

运行结果:

7.求

解题思路:

利用for循环,从1遍历至100,对于第一项,遍历100次后停下;对于第二项,遍历50次后停下;对于第三项,遍历10次后停下。遍历过程中,针对不同情况分别计算三项的值,最后取和。

注:由于第三项非整数,为了提高计算精度,采用双精度double类型

代码:

#include<stdio.h>
#include<math.h>
int main() {
    double sum,sum1 = 0, sum2 = 0, sum3 = 0;
    for (int i = 1; i <= 100; i++) {
        sum1 += i;
        if (i <= 50)
            sum2 += i * i;
        if (i <= 10)
            sum3 += 1.0 / i;
    }
    sum = sum1 + sum2 + sum3;
    printf("计算结果为:%lf\n", sum);
    return 0;
}

运行结果:

8.输出所有的“水仙花数”,所谓“水仙花数”是指一个3位数,其各位数字立方和等于该数本身。例如,153是一水仙花数,因为153=1^3+5^3+3^3。

解题思路:

根据常识可得,所有的三位数范围为:100~999。

利用for循环,依次判断100~999内的每一个数是否为水仙花数,若是则输出。

代码:

#include<stdio.h>
int main() {
    int a, b, c;
    printf("输出所有的水仙花数:\n");
    for (int i = 100; i < 1000; i++) {
        a = i / 100;                    //a为i百位上的数字
        b = i % 100 / 10;               //b为i十位上的数字 
        c = i % 100 % 10;               //c为i个位上的数字
        if (i == a * a * a + b * b * b + c * c * c)
            printf("%d\n", i);
    }
    return 0;
}

运行结果:

9.一个数如果恰好等于它的因子之和,这个数就称为“完数”。例如,6的因子为1,2,3,而6=1+2+3,因此6是“完数”。编程序找出1000之内的所有完数,并按下面格式输出其因子:6 its factors are 1,2,3

解题思路:

利用嵌套循环,外层循环变量i从1~1000;内存循环计算i的因子和,记录在sum变量中;每次内存循环结束后,判断i是否等于total,若是,则i为”完数“。

代码:

#include<stdio.h>
int main() {
    int total;        //total记录当前因子的和
    for (int i = 1; i <= 1000; i++) {                
        total = 0;
        for (int j = 1; j < i; j++) {
            if (i % j == 0) {
                total += j;
            }
        }
        //控制输出方式
        if (i == total) {
            printf("%d its factors are ", i);
            for (int j = 1; j < i; j++) {
                if (i % j == 0)
                    printf("%d,", j);
            }
            printf("\n");
        }
    }
    return 0;
}

运行结果:

10.有一个分数序列求出这个数列的前20项之和。

解题思路:

观察可得,后一项的分子等于前一项分子和分母的和、后一项的分母等于前一项的分子。

代码:

#include<stdio.h>
int main() {
    double a = 2.0, b = 1.0, temp,  total = 0;
    for (int i = 1; i <= 20; i++) {
        total += a/b;
        temp = a;        //暂存a的值
        a = a + b;       //把(a+b)的值赋值给a
        b = temp;        //把a的值赋给b
    }
    printf("该数列前20项的和为:%lf", total);
    return 0;
}

运行结果:

11.一个球从100m高度自由落下,每次落地后反弹回原高度的一半,再落下,再反弹。求它在第10次落地时共经过多少米,第10次反弹多高。

解题思路:

  • 反弹高度:第一次反弹高度为100/2;

第二次反弹高度为100/2/2;

第三次反弹高度为100/2/2;

......

第十次反弹高度为100/2/2/2......2;(10个2)

故设置一个变量h等于初始高度100,循环9次,每次自除2,即可得到第9次反弹的高度;最后输出h/2得到第十次的反弹高度。(循环9次是为了能和求解所经路程的循环放在一个for中,详细解释看代码注释部分)。

  • 总路程S:第一次落地时S=100;

第二次落地时S=100+50*2;

第三次落地时S=100+50*2+25*2;

......

故设置一个变量S等于初始时高度100,循环9次,每次S=S+2*h。

注意:从第三次反弹开始,高度为小数,因此采用双精度double类型。

代码:

#include<stdio.h>
int main() {
    double h=100.0, s=100.0;    //h记录小球反弹高度,s记录小球共经过多少米
    for (int i = 1; i < 10; i++) {    //i=1时,h为第1次反弹高度、s为第2次落地时所经过的路程
        h /= 2.0;
        s += 2.0* h;
    }
    //循环结束时,i=9,h为第9次的反弹高度,s为第10次落地时所经过的路程
    printf("小球在第10次落地时共经过%f米;\n第十次反弹高度为:%f米\n", s,h/2);
    return 0;
}

运行结果:

12.猴子吃桃问题。猴子第一天摘下若干个桃子,当即吃了一半,还不过瘾,又多吃了一个。第2天早上又将剩下的桃子吃掉一半,又多吃了一个。以后每天早上都吃了前一天剩下的一半零一个。到第10天早上再想吃时,就只剩一个桃子了。求第1天共摘了多少个桃子?

解题思路:

贪吃猴问题可以反向求解。

第十天只剩1个桃子,则

第9天有 (1+1)*2 = 4个桃子;

第8天有(4+1)*2 = 10个桃子;

.......

设置一个变量peach记录当前桃子数量,赋初值为1,每次peach的值加1乘2得到新的peach值,循环9次后,peach的值为第一天的桃子数。

代码:

#include<stdio.h>
int main() {
    int peach = 1;
    for (int i = 1; i <= 9; i++)        //循环9次:第十天还没吃嘞,一共吃了9天,反向求9天
        peach = (peach + 1) * 2;
    printf("贪吃猴第1天共摘了%d个桃子!\n", peach);
    return 0;
}

运行结果:

13.用迭代法求 。求平方根的迭代公式为 ,要求前后两次求出的x的差的绝对值小于10^-5。

解题思路:

(1)设定一个x的初值为

(2)利用上述公式求出x的下一个值

(3)将带入公式右边的,求出x的下一个值

(4)如此继续下去,直到前后两次求出的x的值()满足以下关系:

代码:

#include<stdio.h>
#include<math.h>
int main() {
    double a, x0, x1;
    printf("请输入a的值:");
    scanf_s("%lf", &a);
    x0 = a / 2;            //不妨设x的初值为a/2,也可以为其他的
    x1 = (x0 + a / x0) / 2;
    while (fabs(x1 - x0) >= pow(10, -5)) {
        x0 = x1;
        x1 = (x0 + a / x0) / 2;
    }
    printf("%f的平方根为:%f", a, x1);
    return 0;
}

运行结果:

14.用牛顿迭代法求下面方程在1.5附近的根:

解题思路:

牛顿迭代法:任意设定一个与真实根接近的值,求出f(),过(,f())点做f(x)的切线,交x轴于点,如此下去...直到足够接近真正的根为止。

画图分析可得:

则迭代公式为:

代码:

#include<stdio.h>
#include<math.h>
int main() {
    double x0, x1, f, fd;        //f表示函数f(x),fd表示f(x)的导数
    x1 = 1.5;
    do {
        x0 = x1;
        f = 2 * x0 * x0 * x0 - 4 * x0 * x0 + 3 * x0 - 6;
        fd = 6 * x0 * x0 - 8 * x0 + 3;
        x1 = x0 - f / fd;
    } while (fabs(x1-x0)>= 1e-5);
    printf("该方程在1.5附近的根为:%f", x1);
    return 0;
}

运行结果:

15.用二分法求下面方程在(-10,10)之间的根;

解题思路:

给定区间 [,] ,若f(x)在区间内单调变化,则可以根据f()和f()的符号来判断f(x)=0在此区间内有无实根。若f()和f()同正或同负,在无实根;若f()和f()异号,则必有一个(且只有一个)实根。当确定[,] 有一个实根后,把区间一分为二,将中点的值赋值给,再判断在哪个小区间内有实根,如此不断进行下去,直到f()无限趋近于0为止。

代码:

#include<stdio.h>
#include<math.h>
int main() {
    double x1, x2, x0, f1, f2, f0;        //f1表示函数f(x1),f2表示函数f(x2),f0表示函数f(x0)
    x1 = -10.0;
    x2 = 10.0;
    do {
        f1 = 2 * x1 * x1 * x1 - 4 * x1 * x1 + 3 * x1 - 6;
        f2 = 2 * x2 * x2 * x2 - 4 * x2 * x2 + 3 * x2 - 6;
        x0 = (x1 + x2) / 2;
        f0 = 2 * x0 * x0 * x0 - 4 * x0 * x0 + 3 * x0 - 6;
        if ((f1 * f0) < 0)        //根在左区间
            x2 = x0;
        else                    //根在右区间          
            x1 = x0;

    } while (fabs(f0)>=1e-5);
    printf("方程在[-10,10]之间的根为%f", x0);
    return 0;
}

运行结果:

16.输出以下图案:

解题思路:

将整个图像分为上四行和下三行分别处理输出:

  • 上四行:

第0行,3个空格,1个*;

第1行,2个空格,3个*;

第2行,1个空格,5个*;

第3行,0个空格,7个*;

可以推断出:空格数=3-行数 *数=行数*2+1

  • 下三行:

第0行,1个空格,5个*;

第1行,2个空格,3个*;

第2行,3个空格,1个*;

可以推断出:空格数=行数+1 *数=5-2*行数

代码:

#include<stdio.h>
int main() {
    for (int i = 0; i <= 3; i++) {        //控制上面4行
        for(int j = 0; j <= 2-i; j++)    //控制空格
            printf(" ");
        for (int k = 0; k <= 2*i; k++)        //控制*
            printf("*");
        printf("\n");
    }
    for (int i = 0; i <= 2; i++) {
        for (int j = 0; j <= i; j++)
            printf(" ");
        for (int k = 0;k <= 4-(2*i); k++)
            printf("*");
        printf("\n");
    }
    return 0;
}

运行结果:

17.两个乒乓球队进行比赛,各处出人。甲队为A,B,C 3人,乙队为X,Y,Z 3人。以抽签决定比赛名单。有人向队员打听比赛的名单,A说他不和X比,C说他不和X,Z比,请编程找出3对赛手名单。

解题思路:

假设A与i比赛,B与j比赛,C与k比赛。i,j,k 分别是X、Y、Z之一,且i,j,k互不相等。

外循环使i由 'X' 变到 'Z' ,中循环使j由 'X' 变到 'Z'(i、j不应相等)。对每一组i、j的值,找到复合条件的k值。k同样也可能是 'X'、'Y'、'Z'之一,但k也不应与i、j相等。在i!=j!=k的条件下,再把i!= 'X'和k!='X' 和k!='Z'的i、j、k输出即可。

代码:

#include<stdio.h>
int main() {
    char i, j, k;        //假设A的对手是i,B的对手是j,C的对手是K
    for(i='X';i<='Z';i++)
        for (j = 'X'; j <= 'Z'; j++) 
            if (i != j) {
                for (k = 'X'; k < 'Z'; k++) {
                    if (k != i && k != j) {
                        if (i != 'X' && k != 'X' && k != 'Z')
                            printf("A-%c,B-%c,C-%c", i, j, k);
                    }
                }
            }

    return 0;
}

运行结果:


更多章节答案,看我主页哦。

  • 15
    点赞
  • 63
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
以下是第五版《代码答案形式的C语言程序设计》第八的例题答案: 8.1 ```c #include <stdio.h> #define N 5 int main() { int a[N], max, i; printf("Enter array a:\n"); for (i = 0; i < N; i++) scanf("%d", &a[i]); max = a[0]; for (i = 1; i < N; i++) if (a[i] > max) max = a[i]; printf("max=%d\n", max); return 0; } ``` 8.2 ```c #include <stdio.h> #define N 5 int main() { int a[N], i; printf("Enter array a:\n"); for (i = 0; i < N; i++) scanf("%d", &a[i]); printf("Reverse array a:\n"); for (i = N - 1; i >= 0; i--) printf("%d ", a[i]); printf("\n"); return 0; } ``` 8.3 ```c #include <stdio.h> #define N 5 int main() { int a[N], i; printf("Enter array a:\n"); for (i = 0; i < N; i++) scanf("%d", &a[i]); printf("a[0]=%d, a[%d]=%d\n", a[0], N - 1, a[N - 1]); return 0; } ``` 8.4 ```c #include <stdio.h> #define N 5 int main() { int a[N], i, sum = 0; printf("Enter array a:\n"); for (i = 0; i < N; i++) scanf("%d", &a[i]); for (i = 0; i < N; i++) sum += a[i]; printf("sum=%d, average=%.2f\n", sum, (float)sum / N); return 0; } ``` 8.5 ```c #include <stdio.h> #define N 5 int main() { int a[N], i, temp; printf("Enter array a:\n"); for (i = 0; i < N; i++) scanf("%d", &a[i]); for (i = 0; i < N / 2; i++) { temp = a[i]; a[i] = a[N - i - 1]; a[N - i - 1] = temp; } printf("Reverse array a:\n"); for (i = 0; i < N; i++) printf("%d ", a[i]); printf("\n"); return 0; } ``` 8.6 ```c #include <stdio.h> #define N 5 int main() { int a[N], i, j, temp; printf("Enter array a:\n"); for (i = 0; i < N; i++) scanf("%d", &a[i]); for (i = 0; i < N - 1; i++) for (j = i + 1; j < N; j++) if (a[i] > a[j]) { temp = a[i]; a[i] = a[j]; a[j] = temp; } printf("Sort array a:\n"); for (i = 0; i < N; i++) printf("%d ", a[i]); printf("\n"); return 0; } ``` 8.7 ```c #include <stdio.h> #define N 5 int main() { int a[N], i, j, temp; printf("Enter array a:\n"); for (i = 0; i < N; i++) scanf("%d", &a[i]); for (i = 0; i < N - 1; i++) for (j = 0; j < N - i - 1; j++) if (a[j] > a[j + 1]) { temp = a[j]; a[j] = a[j + 1]; a[j + 1] = temp; } printf("Sort array a:\n"); for (i = 0; i < N; i++) printf("%d ", a[i]); printf("\n"); return 0; } ``` 8.8 ```c #include <stdio.h> #define N 5 int main() { int a[N], i; printf("Enter array a:\n"); for (i = 0; i < N; i++) scanf("%d", &a[i]); printf("Max 5 numbers in array a:\n"); for (i = 0; i < 5; i++) printf("%d ", a[i]); printf("\n"); return 0; } ``` 8.9 ```c #include <stdio.h> #define N 5 int main() { int a[N], i, j, temp; printf("Enter array a:\n"); for (i = 0; i < N; i++) scanf("%d", &a[i]); for (i = 0; i < N - 1; i++) for (j = 0; j < N - i - 1; j++) if (a[j] > a[j + 1]) { temp = a[j]; a[j] = a[j + 1]; a[j + 1] = temp; } printf("Median number in array a:\n"); printf("%d\n", a[N / 2]); return 0; } ``` 8.10 ```c #include <stdio.h> #define N 5 int main() { int a[N], i, j, temp; printf("Enter array a:\n"); for (i = 0; i < N; i++) scanf("%d", &a[i]); for (i = 0; i < N - 1; i++) for (j = 0; j < N - i - 1; j++) if (a[j] > a[j + 1]) { temp = a[j]; a[j] = a[j + 1]; a[j + 1] = temp; } printf("Mode number in array a:\n"); for (i = 0; i < N; i++) { int count = 0, k; for (j = i; j < N; j++) if (a[j] == a[i]) count++; for (k = i - 1; k >= 0; k--) if (a[k] == a[i]) break; if (k < 0 && count > 1) printf("%d ", a[i]); } printf("\n"); return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

I-am-Faimon

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值