关于c:C语言程序设计谭浩强第五版-第4章-选择结构程序设计-习题解析与答案

6次阅读

共计 9489 个字符,预计需要花费 24 分钟才能阅读完成。

你也能够上程序咖(https://meta.chengxuka.com),关上大学幕题板块,岂但有答案,解说,还能够在线答题。

题目 1:什么是算术运算? 什么是关系运算? 什么是逻辑运算?

算术运算:

算术运算即“四则运算”,是加法、减法、乘法、除法、乘方、开方等几种运算的统称。

其中加减为一级运算,乘除为二级运算,乘方、开方为三级运算。在一道算式中,如果有多级运算存在,则应先进行高级运算,再进行低一级的运算。

C 语言中的算熟运算符包含:+、-、*、/、++、–、% 等品种。

如果只存在同级运算;则从左至右的程序进行;如果算式中有括号,则应先算括号里边,再按上述规定进行计算。

示例:$ (1 + 1)^{2} * 4+5 * 3$

解析:

先进行括号内运算 1 +1,而后进行乘方运算失去后果 4.
接下来与 4 相乘,失去后果 16
因为乘法优先级大于加法,因而先进行 5 *3,失去后果 15
最终相加失去后果 31
后果:31

关系运算:

关系的根本运算有两类:一类是传统的汇合运算(并、差、交等),另一类是专门的关系运算(抉择、投影、连贯、除法、外连贯等),而在 C 语言中,关系运算通常被认为是比拟运算,将两个数值进行比拟,判断比拟后果是否合乎给定的条件。

常见的关系运算符包含:<、<=、>、>=、==、!= 等品种。

其中,前 4 种关系运算符 (<、<=、>、>=) 的优先级别雷同,后 2 种 (==、!=) 也雷同。而前 4 种高于后 2 种。

例如, > 优先于 ==。而 > 与 < 优先级雷同。
并且,关系运算符的优先级低于算术运算符,关系运算符的优先级高于赋值运算符(=)。

逻辑运算:

在逻辑代数中,有与、或、非三种根本逻辑运算。示意逻辑运算的办法有多种,如语句形容、逻辑代数式、真值表、卡诺图等。而在 C 语言中,逻辑运算通常用于应用逻辑运算符将关系表达式或其它逻辑量连接起来组成逻辑表达式用来测试虚实值。

常见的逻辑运算符包含:&&、||、! 等品种

&&:与是双目运算符,要求有两个运算对象,示意两个运算对象都成立,则后果为真,否则后果为假。

例如:(a<b) && (x>y),示意 (a<b) 和(x>y)同时成立则为真。

||:是双目运算符,要求有两个运算对象,示意两个运算对象只有任意一个成立,则后果为真,否则后果为假。

例如:(a<b) && (x>y),示意 (a<b) 和(x>y)两个对象中任意一个成立则后果为真。

!是单目运算符,只要求有一个运算对象,示意取运算对象反义,运算对象为真则后果为假,运算对象后果为假则后果为真。

例如:!(a>b),示意 (a>b) 成立时后果为假,不成立时后果为真。

若在一个逻辑表达式中蕴含多个逻辑运算符,则优先秩序为:! > && > ||。当然若一个逻辑表达式中蕴含括号括起来的子逻辑,则优先括号内的子逻辑判断。

示例:

(1>2)||(2>3)&&(4>3) 后果为 0
!(1>2)||(2>3)&&(4>3)后果为 1

注:&& 优先级大于 ||,((2>3)&&(4>3))无奈同时成立,则后果为假,而后与 (1>2) 后果进行逻辑或运算,两者都为假因而第一次后果为假。而第二次! 优先级最高,先对 (1>2) 的后果取逻辑非,失去后果为真,因而后果为真。

题目 2:C 语言中如何示意“真”和“假”? 零碎如何判断一个量的“真”和“假”?

答案:

对于逻辑表达式,若其值为“真 ”,则以 1 示意,若其值为“假”,则以 0 示意。然而在判断一个逻辑量的值时,零碎会以 0 作为“假”,以非 0 作为“真”。例如 3 && 5 的值为“真”,零碎给出 3 && 5 的值为 1。

题目 3:写出上面各逻辑表达式的值。设 a =3,b=4,c=5。
(1) a+b>c && b==c
(2) al| 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

题目 4:有 3 个整数 a,b,c, 由键盘输人,输入其中最大的数。

答案:

办法一:N- S 图见图 4.1

答案代码:

#include <stdio.h>
int main()
{
    int a, b, c;
    printf("请输出 3 个整数:");
    scanf("%d,%d,%d", &a, &b, &c);
    if (a < b)
        if (b < c)
            printf("max=%d\n", c);
        else
            printf("max=%d\n", b);
    else if (a < c)
        printf("max=%d\n", c);
    else
        printf("max=%d\n", a);
    return 0;
}

运行后果:

办法二:应用条件表达式, 能够使程序更扼要、清晰。

#include <stdio.h>
int main()
{
    int a, b, c, temp, max;
    printf("请输出 3 个整数:");
    scanf("%d,%d,%d", &a, &b, &c);
    temp = (a > b) ? a : b;         // 将 a 和 b 中的大者存入 temp 中
    max = (temp > c) ? temp : c; // 将 a 和 b 中的大者与 c 比拟, 取最大者
    printf("3 个整数的最大数是 %d\n", max);
    return 0;
}

运行后果:

题目 5:从键盘输入一个小于 1000 的负数,要求输入它的平方根(如平方根不是整数,则输入其整数局部)。要求在输出数据后先对其进行查看是否为小于 1000 的负数。若不是,则要求从新输出。

解:答案代码:

#include <stdio.h>
#include <math.h>
#define M 1000
int main()
{
    int i, k;

    printf("请输出一个小于 %d 的整数 i:", M);
    scanf("%d", &i);
    if (i > M)
    {printf("输人的数据不符合要求, 请从新输出一个小于 %d 的整数 i;", M);
        scanf("%d", &i);
    }
    k = sqrt(i);
    printf("%d 的平方根的整数局部是 %d\n", i, k);
    return 0;
}

运行后果:

①第一次:输人正确数据。

②第二次:输人不正确数据。

探讨:题目要求输人的数小于 1000,今为了减少程序的灵活性, 定义符号常量 M 为 1000,如果题目要求输出的数小于 10000,只须批改 define 指令即可, 不用批改主函数。

用 if 语句查看输出的数是否符合要求,如果不符合要求应进行相应的解决。从下面的程序看来是很简略的,但在理论利用中是很有用的。因为在程序提供用户应用后,不能保障用户输出的数据都是符合要求的。假若用户输人了不符合要求的数据怎么办?如果没有检查和补救措施,程序是不能供理论应用的。

本程序的解决办法是:揭示用户“输人的数据错了”,要求从新输出。但只揭示一次,再错了怎么办? 在学习了第 5 章循环之后,能够将程序改为屡次查看,直到正确输人为止。程序如下:

#include <stdio.h>
#include <math.h>
#define M 1000
int main()
{
    int i, k;
    printf("请输出一个小于 %d 的整数 i:", M);
    scanf("%d", &i);
    while (i > M)
    {printf("输出的数据不符合要求, 请从新输出一个小于 %d 的整数 i:", M);
        scanf("%d", &i);
    }
    k = sqrt(i);
    printf("%d 的平方根的整数局部是 %d\n", i, k);
    return 0;
}

运行后果:

屡次输出不符合要求的数据,均通不过,直到输出符合要求的数据为止。

这种查看伎俩是很重要的,心愿读者能真正把握。本例只是示意性的,程序比较简单。有了此基础,读者依据此思路齐全能够做到对任何条件进行查看解决,使程序能失常运行,十拿九稳。

题目 6:有一个函数:

$$
y =
\begin{cases}
x + y= 1 & (x \lt 1) \\
2x – 1 & (1 \le x \lt 10) \\
3x – 11 & (x \le 10)
\end{cases}
$$

写程序,输出 x 的值,输入 y 相应的值。

答案代码:

#include <stdio.h>
#include <math.h>
#define M 1000
int main()
{
    int x, y;
    printf("输出 x:");
    scanf("%d", &x);
    if (x < 1) // x<1
    {
        y = x;
        printf("x=%3d,  y=x=%d\n", x, y);
    }
    else if (x < 10) // 1=<x<10
    {
        y = 2 * x - 1;
        printf("x=%d,  y=2*x-1=%d\n", x, y);
    }
    else // x> = 10
    {
        y = 3 * x - 11;
        printf("x=%d,  y=3*x-11=%d\n", x, y);
    }
    return 0;
}

运行后果:

题目 7:有一个函数:

$$
y =
\begin{cases}
-1 & (x \lt 0) \\
0 & (x = 0) \\
1 & (x \gt 0)
\end{cases}
$$

有人别离编写了以下两个程序,请剖析它们是否能实现题目要求。不要急于,上机运行程序,先剖析下面两个程序的逻辑,画出它们的流程图,剖析它们的运行状况。而后上机运行程序,察看并剖析后果。

(1)

#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;
}

解:程序 (1) 的流程图见图 4. 2。

它不能实现题目的要求。如果输人的 x <0,则输入 y =0。请留神 else 与 if 的配对关系。程序 (1) 中的 else 子句是和第 9 行的内嵌的 if 语句配对,而不与第 8 行的 if 语句配对。

运行后果:

x 的值为 -6,输入 y =0,后果显然不对。

(2)

#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;
}

解:程序 (2) 的流程图见图 4.3。

它也不能实现题目的要求。如果输出的 x <0,则输入 y =0。

运行后果:

x 的值为 -4,输入 y =0,后果显然不对。程序 (2) 中的 else 子句是和第 9 行的内嵌的 if 语句配对,而不与第 8 行的 if 语句配对。

肯定要留神 if 与 else 的配对关系。配对关系不随 if 和 else 所呈现的列的地位而扭转,例如程序 (2) 中的 else 与第 8 行的 if 写在同一列,但 else 并不因而而与第 8 行的 if 语句配对,它只和在它后面的离它最近的 if 配对。

请和教材第 4 章例 4.5 程序比照剖析,进一步了解 if-else 的配对规定。

为了使逻辑关系清晰,防止出错,个别把内嵌的 if 语句放在外层的 else 子句中(如例 4.5 中程序 1 那样),这样因为有外层的 else 相隔,内嵌的 else 不会被误认为和外层的 if 配对,而只能与内嵌的 if 配对,这样就不会搞混,若像本习题的程序 (1) 和程序 (2) 那样写就很容易出错。

可与本章例 4.5 中介绍的程序进行比照剖析。

题目 8:给出一百分制问题,要求输入问题等级 ’A’、’B’、’C’、’D’、’E’。90 分以上为 ’A’,80~89 分为 ’B’,70~70 分为 ’C’,60~69 分为 ’D’,60 分以下为 ’E’。

解:答案代码:

#include <stdio.h>
int main()
{
    float score;
    char grade;
    printf("请输出学生问题:");
    scanf("%f", &score);
    while (score > 100 || score < 0)
    {printf("\n 输出有误, 请重输");
        scanf("%f", &score);
    }
    switch ((int)(score / 10))
    {
    case 10:
    case 9:
        grade = 'A';
        break;
    case 8:
        grade = 'B';
        break;
    case 7:
        grade = 'C';
        break;
    case 6:
        grade = 'D';
        break;
    case 5:
    case 4:
    case 3:
    case 2:
    case 1:
    case 0:
        grade = 'E';
    }
    printf("问题是 %5.1f, 相应的等级是 %c\n", score, grade);
    return 0;
}

运行后果:

阐明:对输出的数据进行查看,如小于 0 或大于 100,要求从新输出。(int)(score/10)的作用是将 (score/10) 的值进行强制类型转换,失去一个整型值。例如,当 score 的值为 78 时,(int) (score/10)的值为 7。而后在 switch 语句中执行 case 7 中的语句,使 grade= ‘C’。

题目 9:给一个不多于 5 位的正整数,要求:

①求出它是几位数;

②别离输入每一位数字;

③按逆序输入各位数字,例如原数为 321,应输入 123。

解:

#include <stdio.h>
int main()
{

    int num, indiv, ten, hundred, thousand, ten_thousand, place; // 别离代表个位、十位、百位、千位. 万位和位数
    printf("请输出一个整数(0~99999):");
    scanf("%d", &num);
    if (num > 9999)
        place = 5;
    else if (num > 999)
        place = 4;
    else if (num > 99)
        place = 3;
    else if (num > 9)
        place = 2;
    else
        place = 1;
    printf("位数:%d\n", place);
    printf("毎位数字为:");
    ten_thousand = num / 10000;
    thousand = (int)(num - ten_thousand * 10000) / 1000;
    hundred = (int)(num - ten_thousand * 10000 - thousand * 1000) / 100;
    ten = (int)(num - ten_thousand * 10000 - thousand * 1000 - hundred * 100) / 10;
    indiv = (int)(num - ten_thousand * 10000 - thousand * 1000 - hundred * 100 - ten * 10);
    switch (place)
    {
    case 5:
        printf("%d,%d,%d,%d,%d", ten_thousand, thousand, hundred, ten, indiv);
        printf("\n 反序数字为:");
        printf("%d%d%d%d%d\n", indiv, ten, hundred, thousand, ten_thousand);
        break;
    case 4:
        printf("%d,%d,%d,%d", thousand, hundred, ten, indiv);
        printf("\n 反序数字为:");
        printf("%d%d%d%d\n", indiv, ten, hundred, thousand);
        break;
    case 3:
        printf("%d,%d,%d", hundred, ten, indiv);
        printf("\n 反序数字为:");
        printf("%d% d% d(n", indiv, ten, hundred);
        break;
    case 2:
        printf("%d,%d", ten, indiv);
        printf("\n 反序数字为:");
        printf("%d%d\n", indiv, ten);
        break;
    case 1:
        printf("%d", indiv);
        printf("\n 反序数字为:");
        printf("%dn", indiv);
        break;
    }
    return 0;
}

运行后果:

题目 10:企业发放的奖金依据利润提成。利润 I 低于或等于 100 000 元的,奖金可提成 10%;利润高于 100 000 元,低于 200 000 元(100 000<I≤200 000)时,低于 100 000 元的局部按 10% 提成,高于 100 000 元的局部,可提成 7.5%;200 000<I≤400 000 时,低于 200 000 元的局部仍按上述方法提成(下同)。高于 200 000 元的局部按 5% 提成;400 000<I≤600 000 元时,高于 400 000 元的局部按 3% 提成;600 000<I≤1 000 000 时,高于 600 000 元的局部按 1.5% 提成;I >1 000 000 时,超过 1 000 000 元的局部按 1% 提成。从键盘输入当月利润 I,求应发奖金总数。

要求:

(1)用 if 语句编程序;

(2)用 switch 语句编程序。

解:

(1)用 if 语句编程序。

答案代码:

#include <stdio.h>
int main()
{

    int i;
    double bonus, bon1, bon2, bon4, bon6, bon10;
    bon1 = 100000 * 0.1;
    bon2 = bon1 + 100000 * 0.075;
    bon4 = bon2 + 100000 * 0.05;
    bon6 = bon4 + 100000 * 0.03;
    bon10 = bon6 + 400000 * 0.015;
    printf("请输出利润 i:");
    scanf("%d", &i);
    if (i <= 100000)
        bonus = i * 0.1;
    else if (i <= 200000)
        bonus = bon1 + (i - 100000) * 0.075;
    else if (i <= 400000)
        bonus = bon2 + (i - 200000) * 0.05;
    else if (i <= 600000)
        bonus = bon4 + (i - 400000) * 0.03;
    else if (i <= 1000000)
        bonus = bon6 + (i - 600000) * 0.015;
    else
        bonus = bon10 + (i - 1000000) * 0.01;
    printf("奖金是∶%10.2f\n", bonus);
    return 0;
}

运行后果:

此题的关键在于正确写出每一区间的奖金计算公式。例如利润在 100 000~200 000 元时,奖金应由两局部组成∶

①利润为 100 000 元时应得的奖金,即 100 000 元×0.1。

②100 000 元以上局部应得的奖金,即(num 一 100 000)×0.075 元。

同理,200 000~400 000 元这个区间的奖金也应由两局部组成:

①利润为 200 000 元时应得的奖金,即 100 000×0.1+100 000×0.075。

②200 000 元以上局部应得的奖金,即(num—200 000)×0.05 元。


程序中先把 100 000 元、200 000 元、400 000 元、600 000 元、1 000 000 元各关键点的奖金计算出来,即 bonl1,bon2,bon4,bon6 和 bonl0。而后再加上各区间附加局部的奖金即可。

(2)用 switch 语句编程序。

N- S 图见图 4.4。

答案代码:

#include <stdio.h>
int main()
{

    int i;
    double bonus, bon1, bon2, bon4, bon6, bon10;
    int branch;
    bon1 = 100000 * 0.1;
    bon2 = bon1 + 100000 * 0.075;
    bon4 = bon2 + 200000 * 0.05;
    bon6 = bon4 + 200000 * 0.03;
    bon10 = bon6 + 400000 * 0.015;
    printf("请输出利润 i∶");
    scanf("%d", &i);
    branch = i / 100000;
    if (branch > 10)
        branch = 10;
    switch (branch)
    {
    case 0:
        bonus = i * 0.1;
        break;
    case 1:
        bonus = bon1 + (i - 100000) * 0.075;
        break;

    case 2:
    case 3:
        bonus = bon2 + (i - 200000) * 0.05;
        break;
    case 4:
    case 5:
        bonus = bon4 + (i - 400000) * 0.03;
        break;
    case 6:
    case 7:
    case 8:
    case 9:
        bonus = bon6 + (i - 600000) * 0.015;
        break;
    case 10:
        bonus = bon10 + (i - 1000000) * 0.01;
    }
    printf("奖金是 %10.2f\n", bonus);
    return 0;
}

运行后果:

题目 11:输出 4 个整数,要求按由小到大的程序输入。解∶此题采纳顺次比拟的办法排出其大小程序。在学习了循环和数组当前,能够把握更多的排序办法。

程序如下∶

#include <stdio.h>
int main()
{

    int t, a, b, c, d;
    printf("请输出 4 个数∶");
    scanf("%d,%d,%d,%d", &a, &b, &c, &d);
    printf("a=%d,b=%d,c=%d,d=%d\n", a, b, c, d);
    if (a > b)
    {
        t = a;
        a = b;
        b = t;
    }
    if (a > c)
    {
        t = a;
        a = c;
        c = t;
    }
    if (a > d)
    {
        t = a;
        a = d;
        d = t;
    }
    if (b > c)
    {
        t = b;
        b = c;
        c = t;
    }
    if (b > d)
    {
        t = b;
        b = d;
        d = t;
    }
    if (c > d)
    {
        t = c;
        c = d;
        d = t;
    }
    printf("排序后果如下∶\n");
    printf("%d %d %d %d \n", a, b, c, d);
    return 0;
}

运行后果:

题目 12:有 4 个圆塔,圆心别离为(2,2)、(一 2,2)、(—2,一 2)、(2,一 2),圆半径为 1,见图 4.5。这 4 个塔的高度为 10m,塔以外无建筑物。今输出任一点的坐标,求该点的修建高度(塔外的高度为零)。

解:N- S 图见图 4.6。

答案代码:

#include <stdio.h>
int main()
{

    int h = 10;
    float x1 = 2, y1 = 2, x2 = -2, y2 = 2, x3 = -2, y3 = -2, x4 = 2, y4 = -2, x, y, d1, d2, d3, d4;
    printf("请输出一个点(x,y)∶");
    scanf("%f,%f", &x, &y); // 求该点到各中心点间隔
    d1 = (x - x4) * (x - x4) + (y - y4) * (y - y4);
    d2 = (x - x1) * (x - x1) + (y - y1) * (y - y1);
    d3 = (x - x2) * (x - x2) + (y - y2) * (y - y2);
    d4 = (x - x3) * (x - x3) + (y - y3) * (y - y3);
    if (d1 > 1 && d2 > 1 && d3 > 1 && d4 > 1)
        h = 0; // 判断该点是否在塔外
    printf("该点高度为 %d\n", h);
    return 0;
}

运行后果:

对于平年问题的阐明:

在教材第 4 章中举了计算平年的例子,有的读者对平年规定不分明,纷纷来信询问。因而,有必要在此对平年的规定作一些阐明:

地球绕太阳转一周的理论工夫为 365 天 5 小时 48 分 46 秒。如果一年只有 365 天,每年就多出 5 个多小时。4 年多出的 23 小时 15 分 4 秒,差不多等于一天。于是决定每 4 年减少 1 天。然而,它比一天 24 小时又少了约 45 分钟。如果每 100 年有 25 个平年,就少了 18 时 43 分 20 秒,这就差不多等于一天了,这显然是不适合的。

能够算出,每年多出 5 小时 48 分 46 秒,100 年就多出 581 小时 16 分 40 秒。而 25 个平年须要 25×24=600 小时。581 小时 16 分 40 秒只够 24 个平年(24×24=576 小时),于是决定每 100 年只安顿 24 个平年(世纪年不作为平年)。然而这样每 100 年又多出 5 小时 16 分 40 秒(581 小时 16 分 40 秒—576 小时),于是又决定每 400 年减少一个平年。这样就比拟靠近理论状况了。

依据以上状况,决定平年按以下规定计算:

平年应能被 4 整除(如 2004 年是平年,而 2001 年不是平年),但不是所有能被 4 整除的年份都是平年。在能被 100 整除的年份中,只有同时能被 400 整除的年份才是平年(如 2000 年是平年),能被 100 整除而不能被 400 整除的年份(如 1800、1900、2100)不是平年。这是国内公认的规定。只说 ” 能被 4 整除的年份是平年 ” 是不精确的。


教材中介绍的办法和程序是正确的。

正文完
 0