栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

16章练习题-C语言程序设计:现代方法(第2版)课后答案

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

16章练习题-C语言程序设计:现代方法(第2版)课后答案

16.1节
1. 在下列声明中,结构x和结构y都拥有名为x和y的成员:
struct { int x, y; } x;
struct { int x, y; } y;
单独出现时,这两个声明是否合法?两个声明是否可以同时出现在程序中呢?验证你的答案。

     两种声明单独和一起都是合法的:结构的成员变量只能用.操作符来访问,
而且它们的范围只限于它们的结构。


2. (a) 声明名为c1、c2和c3的结构变量,每个结构变量都拥有double类型的成员real和imaginary。
(b) 修改(a)中的声明,使c1的成员初始值为0.0和1.0,而c2的成员初始值为1.0和0.0。(c3不初始化。)
(c) 编写语句用来把c2的成员复制给c1。这项操作是否可以在一条语句中完成,还是必须要两条语句?
(d) 编写语句把c1和c2的对应成员进行相加,并且把结果存储在c3中。

(a)
struct {
    double real;
    double imaginary;
} c1, c2, c3;

(b)
struct {
    double real;
    double imaginary;
} c1 = {0.0, 1.0}, c2 = {1.0, 0.0}, c3;

(c)
c1 = c2;

(d)
c3.real = c1.real + c2.real;
c4.imaginary = c1.imaginary + c2.imaginary;


16.2节
3. (a) 说明如何为具有double类型的成员real和imaginary的结构声明名为complex的标记。
(b) 利用标记complex来声明名为c1、c2和c3的变量。
(c) 编写名为make_complex的函数,此函数用来把两个实际参数(类型都是double类型)存储在complex结构中,然后返回此结构。
(d) 编写名为add_complex的函数,此函数用来把两个实际参数(都是complex结构)的对应成员相加,然后返回结果(另一个complex结构)。

(a)
struct complex {
    double real;
    double imaginary;
}

(b)
struct complex c1, c2, c3;

(c)
struct complex make_complex(double real, double imaginary) {
    return (struct complex) {real, imaginary};
}

(d)
struct complex add_complex(struct complex a, struct complex b) {

    return (struct complex) {a.real + b.real, a.imaginary + b.imaginary};
}


4. 重做练习题3,这次要求使用名为Complex的类型。

(a)
typedef struct {
    double real;
    double imaginary;
} Complex;

(b)
Complex c1, c2, c3;

(c)
Complex make_complex(double real, double imaginary) {
    return (Complex) {real, imaginary};
}

(d)
Complex add_complex(Complex a, Complex b) {
    return (Complex) {a.real + b.real, a.imaginary + b.imaginary};
}


5. 编写下列函数,假定date结构包含三个成员:month、day和year(都是int类型)。
(a) int day_of_year(struct date d);
返回d是一年中的第多少天(1和366之间的整数)。
(b) int compare_dates(struct date d1, struct date d2);
如果日期d1在d2之前,返回  1;如果d1在d2之后,返回+1;如果d1和d2相等,返回0。

(a)
int day_of_year(struct date d) {
    int res = 0, i;
    const int days_month[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    if (d.month > 1 && ((d.year % 4 == 0 && d.year % 100 != 0) 
        || d.year % 400 == 0))
        res++;
    for (i = 0; i < d.month; i++)
        res += days_month[i];
    return res + d.day;
}

(b)
int compare_dates(struct date d1, struct date d2) {
    int d1day = day_of_year(d1);
    int d2day = day_of_year(d2);
    if (d1day > d2day)
        return -1;
    else if (d1day < d2day)
        return 1;
    else
        return 0;
}


6. 编写下列函数,假定time结构包含三个成员:hours、minutes和seconds(都是 int 类型)。
struct time split_time(long total_seconds);
total_seconds是从午夜开始的秒数。函数返回一个包含等价时间的结构,等价的时间用小时
(0~23)、分钟(0~59)和秒(0~59)表示。

struct time split_time(long total_seconds) {

    struct time t;
    t.hours = total_seconds / 3600;
    total_seconds %= 3600;
    t.minutes = total_seconds / 60;
    total_seconds %= 60;
    t.seconds = total_seconds;
    return t;
}


7. 假定fraction结构包含两个成员:numerator和denominator(都是int类型)。编写函数完成下列分数运算。

(a) 把分数f化为最简形式。提示:为了把分数化为最简形式,首先计算分子和分母的最大公约数(GCD),然后把分子和分母都除以该最大公约数。
(b) 把分数f1和f2相加。
(c) 从分数f1中减去分数f2。
(d) 把分数f1和f2相乘。
(e) 用分数f1除以分数f2。
分数f、f1和f2都是struct fraction类型的参数。每个函数返回一个struct fraction类型的值。
(b)~(e)中函数返回的分式应为最简形式。提示:可以使用(a)中的函数辅助编写(b)~(e)中的函数。

(a)
struct fraction reduce_fraction(struct fraction f) {
    int temp;
    int n = f.numerator, d = f.denominator;

    while (n % d != 0) {
        temp = d;
        d = n % d;
        n = temp;
    }
    f.numerator /= d;
    f.denominatro /= d;
    return f;
}

(b)
struct fraction add_fractions(struct fraction f1, struct fraction f2) {
    return reduce_fraction((struct fraction) {f1.numerator * f2.denominator +
        f2.numerator * f1.denominator, f1.denominator * f2.denominator});
}

(c)
struct fraction subtract_fractions(struct fraction f1, struct fraction f2) {
    return reduce_fraction((struct fraction) {f1.numerator * f2.denominator -
        f2.numerator * f1.denominator, f1.denominator * f2.denominator});
}

(d)
struct fraction multiply_fractions(struct fraction f1, struct fraction f2) {
    return reduce_fraction((struct fraction) {f1.numerator * f2.numerator,
        f1.denominator * f2.denominator});
}

(e)
struct fraction divide_fractions(struct fraction f1, struct fraction f2) {
    return reduce_fraction((struct fraction) {f1.numerator * f2.denominator,
        f1.denominator * f2.numerator});
}


8. 设color是如下的结构:
struct color {
        int red;
        int green;
        int blue;
};
(a) 为struct color类型的const变量MAGENTA编写声明,成员的值分别为255、0和255。
(b) (C99)重复上题,但是使用指定初始化式。要求不指定green的值,使其默认为0。

(a)
const struct color MAGENTA = {255, 0, 255};

(b)
const struct color MAGENTA = {.red = 255, .blue = 255};


9. 编写下列函数。(color结构的定义见练习题8。)
(a) struct color make_color(int red, int green, int blue);
函数返回一个包含指定的red、green和blue值的color结构。如果参数小于0,把结构的对应成
员置为0。如果参数大于255,把结构的对应成员置为255。
(b) int getRed(struct color c);
函数返回 c 的 red 成员的值。
(c) bool equal_color(struct color color1, struct color color2);
如果color1和color2的对应成员相等,函数返回true。
(d) struct color brighter(struct color c);
函数返回一个表示颜色c的更亮版本的color结构。该结构等同于c,但每个成员都除以了0.7(把结果截断为整数)。但是,有三种特殊情形:(1)如果c的所有成员都为0,函数返回一个所有成员的值都为3的颜色;(2)如果c的任意成员比0大且比3小,那么在除以0.7之前将其置为3;(3)如果除以0.7之后得到了超过255的成员,将其置为255。
(e) struct color darker(struct color c);
函数返回一个表示颜色c的更暗版本的color结构。该结构等同于c,但每个成员都乘以了0.7(把结果截断为整数)。

(a)
struct color make_color(int red, int green, int blue) {
    if (red < 0)
        red = 0;
    else if (red > 255)
        red = 255;
    if (green < 0)
        green = 0;
    else if (green > 255)
        green = 255;
    if (blue < 0)
        blue = 0;
    else if (blue > 255)
        blue = 255;

    return (struct color) {red, green, blue};
}

(b)
int getRed(struct color c) {
    return c.red;
}

(c)
bool equal_color(struct color color1, struct color color2) {
    return (color1.red == color2.red && color1.green == color2.green &&
        color1.blue == color2.blue);

(d)
struct color brighter(struct color c) {
    if (c.red + c.green + c.blue == 0)
        return (struct color) {3, 3, 3};

    if (c.red > 0 && c.red < 3)
        c.red = 3;
    if (c.green > 0 && c.green < 3)
        c.green = 3;
    if (c.blue > 0 && c.blue < 3)
        c.blue = 3;

    c.red = (int) c.red / 0.7;
    c.green = (int) c.green / 0.7;
    c.blue = (int_ c.blue / 0.7;

    if (c.red > 255)
        c.red = 255;
    if (c.green > 255)
        c.green = 255;
    if (c.blue > 255)
        c.blue = 255;

    return c;
}

(e)
struct color darker(struct color c) {
    c.red = (int) c.red * 0.7;
    c.green = (int) c.green * 0.7;
    c.blue = (int) c.blue * 0.7;

    return c;
}


16.3节
10. 下列结构用来存储图形屏幕上的对象信息。
struct point { int x, y; };
struct rectangle { struct point upper_left, lower_right; };
结构point用来存储屏幕上点的x和y坐标,结构rectangle用来存储矩形的左上和右下坐标点。编写函数,要求可以在rectangle结构变量r上执行下列操作,且r作为实际参数传递。
(a) 计算r的面积。
(b) 计算r的中心,并且把此中心作为point值返回。如果中心的x或y坐标不是整数,在point结构中存储截断后的值。
(c) 将r沿x轴方向移动x个单位,沿 y 轴移动y个单位,返回r修改后的内容。(x和y是函数的另外两个实际参数。)
(d) 确定点p是否位于r内,返回true或者false。(p是struct point类型的另外一个实际参数。)

(a)
int area_rectangle(struct rectangle r) {
    return (r.lower_right.x - r.upper_left.x) 
           * (r.lower_right.y - r.upper_left.y);
}

(b)
struct point rectangle_center(struct rectangle r) {
    return (struct point) {(r.lower_right.x - r.upper_left.x) / 2,
                           (r.lower_right.y - r.upper_left.y) / 2};
}

(c)
struct rectangle move_rect(struct rectangle r, int x, int y) {
    r.upper_left.x += x;
    r.upper_left.y += y;
    r.lower_right.x += x;
    r.lower_right.y += y;
    return r;
}

(d)
bool is_within_rect(struct rectangle r, struct point p) {
    return (p.x > r.upper_left.x && p.x < r.lower_right.x
            && p.y > r.upper_left.y && p.y < r.lower_right.y);
}


16.4节
11. 假设s是如下结构:

struct {
        double a;
        union {
                char b[4];
                double c;
                int d;
                } e;
        char f[4];
} s;
如果char类型值占有1个字节,int类型值占有4个字节,而double类型值占有8个字节,那么C编译
器将为s分配多大的内存空间?(假设编译器没有在成员之间留“空洞”。)

C编译器将为s结构分配20个字节,这样e将被分配8个字节。


12. 假设u是如下联合:
union {
        double a;
        struct {
                char b[4];
                double c;
                int d;
                } e;
        char f[4];
} u;
如果char类型值占有1个字节,int类型值占有4个字节,而double类型值占有8个字节,那么C编译
器将为u分配多大的内存空间?(假设编译器没有在成员之间留“空洞”。)

C编译器将为u联盟分配16个字节,这样它最大的成员e将有16个字节分配给自己。


13. 假设s是如下结构(point是在练习题10中声明的结构标记):
struct shape {
        int shape_kind;
        struct point center;
        union {
                struct {
                        int height, width;
                } rectangle;
                struct {
                        int radius;
                } circle;
        } u;
} s;
如果shape_kind的值为RECTANGLE,那么height和width成员分别存储矩形的两维。如果
shape_kind的值为CIRCLE,那么radius成员存储圆形的半径。请指出下列哪些语句是合法的,并
说明如何修改不合法的语句。
(a) s.shape_kind = RECTANGLE;
(b) s.center.x = 10;
(c) s.height = 25;
(d) s.u.rectangle.width = 8;
(e) s.u.circle = 5;
(f) s.u.radius = 5;

(a)、(b)和(d)是合法的声明,
(c) 必须更改以访问 联合rectangle中的结构u:s.u.rectangle.height = 25;
(e) 必须更改以访问联合内结构 的radius成员
(f) 必须这样做:s.u.circle.radius = 5;.


14. 假设shape是练习题13中声明的结构标记。编写函数用来在shape类型结构变量s上完成下列操作,并且s作为实际参数传递给函数。
(a) 计算s的面积。
(b) 将s沿x轴方向移动x个单位,沿 y 轴移动y个单位,返回s修改后的内容。(x和y是函数的另外两个实际参数。)
(c) 把s缩放c倍(c是double类型的值),返回s修改后的内容。(c是函数的另外一个实际参数。)

(a)
double shape_area(struct shape s) {
    if (s.shape_kind == RECTANGLE)
        return s.u.rectangle.height * s.u.rectangle.width;
    else
        return 3.1415 * s.u.circle.radius * s.u.circle.radius;
}

(b)
struct shape shape_move(struct shape s, int x, int y) {
    s.center.x += x;
    s.center.y += y;

    return s;
}

(c)
struct shape shape_scale(struct shape s, double c) {
    if (s.shape_kind == RECTANGLE) {
        s.u.rectangle.height *= c;
        s.u.rectangle.width *= c;
    } else
        s.u.circle.radius *= c;
    return s;
}

16.5节
15. (a) 为枚举声明标记,此枚举的值表示一周中的7天。
(b) 用typedef定义(a)中枚举的名字。

(a)
enum weekdays = {MONDAY, TUESDAY, WEDNESDAY, THURSDAY, 
                 FRIDAY, SATURDAY, SUNDAY};

(b)
typedef enum {MONDAY, TUESDAY, WEDNESDAY, THURSDAY,
              FRIDAY, SATURDAY, SUNDAY} Day;

 16. 下列关于枚举常量的叙述哪些是正确的?
(a) 枚举常量可以表示程序员指定的任何整数。
(b) 枚举常量具有的性质和用#define创建的常量的性质完全一样。
(c) 枚举常量的默认值为0, 1, 2, …。
(d) 枚举中的所有常量必须具有不同的值。
(e) 枚举常量在表达式中可以作为整数使用。

(a)、(c)和(e)是对的。(b)是错误的,因为枚举常量可以有块范围,并且不被预处理程序评估。
(d)是明显的错误。

enum polygon_sides {
    SQUARE = 4,
    RECTANGLE = 4,
    CIRLCE = 0,
    TRIANGLE = 3,
    PENTAGON = 5,
    HEXAGON = 6,
};


17. 假设b和i以如下形式声明:
enum {FALSE, TRUE} b;
int i;
下列哪些语句是合法的?哪些是“安全的”(始终产生有意义的结果)?
(a) b = FALSE; (b) b = i;
(c) b++; (d) i = b;
(e) i = 2 * b + 1;

所有的语句都是合法的,但是(b)和(c)是潜在的不安全的,
因为递增b或将i的值分配给b可能导致b的值超出其正常范围。


18. (a) 国际象棋棋盘的每个方格中可能有一个棋子,即兵、马、象、车、皇后或国王,也可能为空。每个棋子可能为黑色的也可能是白色的。请定义两个枚举类型:Piece用来包含7种可能的值(其中一种为“空”),Color用来表示2种颜色。
(b) 利用(a)中的类型,定义名为Square的结构类型,使此类型可以存储棋子的类型和颜色。
(c) 利用(b)中的Square类型,声明一个名为board的8×8的数组,使此数组可以用来存储棋盘上的全部内容。
(d) 给(c)中的声明添加初始化式,使board的初始值对应国际象棋比赛开始时的棋子布局。没有棋子的方格值为“空”且颜色为黑色。

(a)
typedef enum {EMPTY, PAWN, KNIGHT, BISHOP, ROOK, QUEEN, KING} Piece;
typedef enum {BLACK, WHITE} Color;

(b)
typedef struct { Piece; Color; } Square;

(c)
Square[8][8] board;

(d)
Square[8][8] board = {
    {{ROOK,  WHITE}, {KNIGHT, WHITE}, {BISHOP, WHITE}, {QUEEN, WHITE},
     {KING,  WHITE}, {BISHOP, WHITE}, {KNIGHT, WHITE}, {ROOK,  WHITE}},
    {{PAWN,  WHITE}, {PAWN,   WHITE}, {PAWN,   WHITE}, {PAWN,  WHITE},
     {PAWN,  WHITE}, {PAWN,   WHITE}, {PAWN,   WHITE}, {PAWN,  WHITE}},
    {{EMPTY, BLACK}, {EMPTY,  BLACK}, {EMPTY,  BLACK}, {EMPTY, BLACK},
     {EMPTY, BLACK}, {EMPTY,  BLACK}, {EMPTY,  BLACK}, {EMPTY, BLACK}},
    {{EMPTY, BLACK}, {EMPTY,  BLACK}, {EMPTY,  BLACK}, {EMPTY, BLACK},
     {EMPTY, BLACK}, {EMPTY,  BLACK}, {EMPTY,  BLACK}, {EMPTY, BLACK}},
    {{EMPTY, BLACK}, {EMPTY,  BLACK}, {EMPTY,  BLACK}, {EMPTY, BLACK},
     {EMPTY, BLACK}, {EMPTY,  BLACK}, {EMPTY,  BLACK}, {EMPTY, BLACK}},
    {{PAWN,  BLACK}, {PAWN,   BLACK}, {PAWN,   BLACK}, {PAWN,  BLACK},
     {PAWN,  BLACK}, {PAWN,   BLACK}, {PAWN,   BLACK}, {PAWN,  BLACK}},
    {{ROOK,  BLACK}, {KNIGHT, BLACK}, {BISHOP, BLACK}, {QUEEN, BLACK},
     {KING,  BLACK}, {BISHOP, BLACK}, {KNIGHT, BLACK}, {ROOK,  BLACK}},
};


19. 声明一个具有如下成员的结构,其标记为pinball_machine:
name——字符串,最多有40个字符
year——整数,表示制造年份
type——枚举类型的值,可能的取值为EM(机电式的)和SS(固态电路的)
players——整数,表示玩家的最大数目

struct pinball_machine {
    char[40] name;
    int year;
    enum { EM, SS } type;
    int players;
};


20. 假定direction变量声明如下:
enum {NORTH, SOUTH, EAST, WEST} direction;
设x和y为int类型的变量。编写switch语句测试direction的值,如果值为EAST就使x增1,如果值为WEST就使x减1,如果值为SOUTH就使y增1,如果值为NORTH就使y减1。

switch(direction) {
    case NORTH: y--;
                break;
    case SOUTH: y++;
                break;
    case EAST:  x++;
                break;
    case WEST:  x--;
                break;
    default:    break;
}


21. 下列声明中,枚举常量的整数值分别是多少?
(a) enum {NUL, SOH, STX, ETX};
(b) enum {VT = 11, FF, CR};
(c) enum {SO = 14, SI, DLE, CAN = 24, EM};
(d) enum {ENQ = 45, ACK, BEL, LF = 37, ETB, ESC};

(a)
0, 1, 2 and 3.

(b)
11, 12 and 13.

(c)
14, 15, 16, 24 and 25.

(d)
45, 46, 47, 37, 38 and 39


22. 枚举chess_pieces声明如下:
enum chess_pieces {KING, QUEEN, ROOK, BISHOP, KNIGHT, PAWN};
(a) 为名为piece_value的整数常数数组编写声明(包含一个初始化式),这个数组存储数200、9、5、3、3和1分别表示从国王到兵这些棋子。(国王的值实际上是无穷大,因为一旦王被擒(将死)则游戏结束,但一些象棋软件会给国王分配一个类似200的较大值。)
(b)(C99)重复上题,但是使用指定初始化式来初始化数组。把chess_pieces中的枚举常量作为指示符的下标使用。(提示:参考“问与答”部分的最后一个问题。)

(a)
const int piece_value[] = {200, 9, 5, 3, 3, 1};

(b)
const int piece_value[] = {
    [KING] = 200, 
    [QUEEN] = 9,
    [ROOK] = 5, 
    [BISHOP] = 3,
    [KNIGHT] = 3,
    [PAWN] = 1
};

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/913472.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号