C Primer Plus 第十五章 课后答案

目录

 

复习题

1.把下面的十进制转换为二进制:

a.3        b.13        c.59        d.119

2.将下面的二进制值转换为十进制、八进制和十六进制的形式:

a.00010101        b.01010101        c.01001100        d.10011101

3.对下面的表达式求值,假设每个值都为8位:

a.~3        b.3 & 6        c.3 | 6        d.1 | 6

e.3 ^ 6      f.7 >> 1       g.7 << 2

4.对下面的表达式求值,假设每个值都为8位:

a.~0        b.!0        c.2 & 4        d.2 && 4        e.2 | 4        f.2 || 4        g.5 << 3

5.因为ASCII码只使用最后7位,所以有时需要用掩码关闭其他位,其相应的二进制掩码是什么?分别用十进制、八进制和十六进制来表示这个掩码

6.程序清单15.2中,可以把下面的代码:

程序照常工作。这是否意味着*=2等同于<<=1?+=是否等同于|=?

7.

a.Tinkerbell计算机有一个硬件字节可读入程序。该字节包含以下信息:

Tinkerbell和IBM PC一样,从右往左填充结构位字段。创建一个适合存放这些信息的位字段模板。

b.Klinkerbell与Tinkerbell类似,但是它从左往右填充结构位字段。请为Klinkerbell创建一个相应的位字段模板

编程练习

1.编写一个函数,把二进制字符串转换为一个数值。例如,有下面的语句:

char * pbin = "01001001";

那么把pbin作为参数传递给该函数后,它应该返回一个int类型的值25

2.编写一个程序,通过命令行参数读取两个二进制字符串,对这两个二进制数使用~运算符、&运算符、|运算符和^运算符,并以二进制字符串形式打印结果(如果无法使用命令行环境,可以通过交互式让程序读取字符串)

3.编写一个函数,接受一个 int 类型的参数,并返回该参数中打开位的数量。在一个程序中测试该函数

4.编写一个程序,接受两个int类型的参数:一个是值;一个是位的位置。如果指定位的位置为1,该函数返回1;否则返回0。在一个程序中测试该函数

5.编写一个函数,把一个 unsigned int 类型值中的所有位向左旋转指定数量的位。例如,rotate_l(x, 4)把x中所有位向左移动4个位置,而且从最左端移出的位会重新出现在右端。也就是说,把高阶位移出的位放入低阶位。在一个程序中测试该函数

6.设计一个位字段结构以储存下面的信息。

字体ID:0~255之间的一个数;

字体大小:0~127之间的一个数;

对齐:0~2之间的一个数,表示左对齐、居中、右对齐;

加粗:开(1)或闭(0);

斜体:开(1)或闭(0);

在一个程序中使用该结构来打印字体参数,并使用循环菜单来让用户改变参数。例如,该程序的一个运行示例如下:


复习题

1.把下面的十进制转换为二进制:

a.3        b.13        c.59        d.119

a. 0000 0011        b. 0000 1101        c. 0011 1011        d. 0111 0111

2.将下面的二进制值转换为十进制、八进制和十六进制的形式:

a.00010101        b.01010101        c.01001100        d.10011101

a. 21 025 0x15        b. 85 0125 0x55        c. 76 0114 0x4C      d. 157 0235 0x9D

3.对下面的表达式求值,假设每个值都为8位:

a.~3        b.3 & 6        c.3 | 6        d.1 | 6

e.3 ^ 6      f.7 >> 1       g.7 << 2

a. 252(256 - 1 - 3)        b. 2        c. 7       d. 7        e. 5        f. 3        g. 28

4.对下面的表达式求值,假设每个值都为8位:

a.~0        b.!0        c.2 & 4        d.2 && 4        e.2 | 4        f.2 || 4        g.5 << 3

a. 255        b. 1(not false)        c. 0        d. 1        e. 6        f. 1        g. 40

5.因为ASCII码只使用最后7位,所以有时需要用掩码关闭其他位,其相应的二进制掩码是什么?分别用十进制、八进制和十六进制来表示这个掩码

  1. 0111 1111
  2. 127
  3. 0177
  4. 0x7F

6.程序清单15.2中,可以把下面的代码:

while (bits-- > 0) 
{ 
    mask |= bitval; 
    bitval <<= 1; 
} 
替换成: 
while (bits-- > 0) 
{    
    mask += bitval; 
    bitval *= 2;
}

程序照常工作。这是否意味着*=2等同于<<=1?+=是否等同于|=?

  1. 是(越界处理效果也一样)

7.

a.Tinkerbell计算机有一个硬件字节可读入程序。该字节包含以下信息:

Tinkerbell和IBM PC一样,从右往左填充结构位字段。创建一个适合存放这些信息的位字段模板。

struct a_dirver
{
    unsigned int ddnum : 2;
    unsigned int       : 1;
    unsigned int crnum : 2;
    unsigned int       : 1;
    unsigned int hdnum : 2;
};

b.Klinkerbell与Tinkerbell类似,但是它从左往右填充结构位字段。请为Klinkerbell创建一个相应的位字段模板

struct b_dirver
{
    unsigned int hdnum : 2;
    unsigned int       : 1;
    unsigned int crnum : 2;
    unsigned int       : 1;
    unsigned int ddnum : 2;
};

编程练习

1.编写一个函数,把二进制字符串转换为一个数值。例如,有下面的语句:

char * pbin = "01001001";

那么把pbin作为参数传递给该函数后,它应该返回一个int类型的值25

#include <stdio.h>
#include <stdlib.h>

int trans(char *a)
{
    int sum = 0;
    while(*a)
    {
        sum *= 2;
        sum += *a - '0';
        a++;
    }
    return sum;
}

int main(void)
{
    char a[50];
    gets(a);
    printf("%d\n", trans(a));
    return 0;
}

2.编写一个程序,通过命令行参数读取两个二进制字符串,对这两个二进制数使用~运算符、&运算符、|运算符和^运算符,并以二进制字符串形式打印结果(如果无法使用命令行环境,可以通过交互式让程序读取字符串)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void funca(char *a, char *b)
{
    putchar('\n');
    while(*a && *b)
    {
        int x = ((*a) - '0') & ((*b) - '0');
        putchar(x + '0');
        a++;
        b++;
    }
    putchar('\n');
}

void funcb(char *a, char *b)
{
    putchar('\n');
    while(*a && *b)
    {
        int x = ((*a) - '0') ^ ((*b) - '0');
        putchar(x + '0');
        a++;
        b++;
    }
    putchar('\n');
}

void funcc(char *a, char *b)
{
    putchar('\n');
    while(*a && *b)
    {
        int x = ((*a) - '0') | ((*b) - '0');
        putchar(x + '0');
        a++;
        b++;
    }
    putchar('\n');
}

void funcd(char *a, char *b)
{
    putchar('\n');
    while(*a)
    {
        int x = (((*a) - '0') + 1) % 2;//不能直接对(*a) - '0'取反,此时它是一个1字节的变量
        putchar(x + '0');
        a++;
    }
    putchar('\n');
    while(*b)
    {
        int x = ((*b) - '0' + 1) % 2;
        putchar(x + '0');
        b++;
    }
    putchar('\n');
}

int main(int argc, char **argv)
{
    if(argc != 4)
    {
        fprintf(stderr, "Usage:%s [string] [string] [char]\n", argv[0]);
        exit(EXIT_FAILURE);
    }
    char ch;
    ch = argv[3][0];
    switch(ch)
    {
        case '1'://不能用位运算符作为识别符号,不符合命令行格式
            funca(argv[1], argv[2]);
            break;
        case '2':
            funcb(argv[1], argv[2]);
            break;
        case '3':
            funcc(argv[1], argv[2]);
            break;
        case '4':
            funcd(argv[1], argv[2]);
            break;
    }
    return 0;
}

3.编写一个函数,接受一个 int 类型的参数,并返回该参数中打开位的数量。在一个程序中测试该函数

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>

const int size = CHAR_BIT * sizeof(int);

int count(int n)
{
    int x = 1, sum = 0;
    for (int i = 0; i < size; ++i)
    {
        if(n & x)
        {
            sum++;
        }
        x <<= 1;
    }
    return sum;
}

int main(int argc, char **argv)
{
    int n;
    scanf("%d", &n);
    printf("%d\n", count(n));
    return 0;
}

4.编写一个程序,接受两个int类型的参数:一个是值;一个是位的位置。如果指定位的位置为1,该函数返回1;否则返回0。在一个程序中测试该函数

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>

const int size = CHAR_BIT * sizeof(int);

int judge(int a, int b)
{
    int x = 1 << (b - 1);
    if(a & x)
    {
        return 1;
    }
    return 0;
}

int main(int argc, char **argv)
{
    int a, b;
    scanf("%d %d", &a, &b);
    printf("%d\n", judge(a, b));
    return 0;
}

5.编写一个函数,把一个 unsigned int 类型值中的所有位向左旋转指定数量的位。例如,rotate_l(x, 4)把x中所有位向左移动4个位置,而且从最左端移出的位会重新出现在右端。也就是说,把高阶位移出的位放入低阶位。在一个程序中测试该函数

//不知道为啥不是彩色的
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>

const int size = CHAR_BIT * sizeof(int);
int ar[CHAR_BIT * sizeof(int)];//变长数组只能在自动内存中创建,所以不能写ar[size]

int retate_l(int a, int b)
{
    int ax[b];
    for (int i = 0; i < b; ++i) {
        ax[i] = a & ar[i];
    }
    a <<= b;
    for (int j = 0; j < b; ++j) {
        a += ax[j] << b;
    }
    return a;
}

int main(int argc, char **argv)
{
    for (int i = 0; i < size; ++i) {
        ar[i] =  1 << (size - i - 1);
    }
    int a, b;
    scanf("%d %d", &a, &b);
    printf("%d\n", retate_l(a, b));
    return 0;
}

6.设计一个位字段结构以储存下面的信息。

字体ID:0~255之间的一个数;

字体大小:0~127之间的一个数;

对齐:0~2之间的一个数,表示左对齐、居中、右对齐;

加粗:开(1)或闭(0);

斜体:开(1)或闭(0);

在一个程序中使用该结构来打印字体参数,并使用循环菜单来让用户改变参数。例如,该程序的一个运行示例如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>

typedef unsigned int un;

struct font
{
    un id       : 7;
    un size     : 6;
    un align    : 2;
    un B        : 1;
    un I        : 1;
    un U        : 1;
}font_a = {1, 12, 0, 0, 0, 0};

const char al[][7] = {"left", "center", "right"};
const char st[][4] = {"off", "on"};

void funcf()
{
    un n;
    printf("Enter font id (0-255):");
    scanf("%u", &n);
    font_a.id = n;
}

void funcs()
{
    un n;
    printf("Enter font size (0-127):");
    scanf("%u", &n);
    font_a.size = n;
}

void funca()
{
    un n;
    printf("Select alignment:\n0)left    1)center    2)right\n");
    scanf("%u", &n);
    font_a.align = n;
}

void funcb()
{
    font_a.B = (font_a.B + 1) % 2;
}

void funci()
{
    font_a.I = (font_a.I + 1) % 2;
}

void funcu()
{
    font_a.U = (font_a.U + 1) % 2;
}

void Print()
{
    puts("ID      SIZE    ALIGN   B       I       U");
    printf("%-8u%-8u%-8s%-8s%-8s%-8s\n", font_a.id, font_a.size, al[font_a.align], st[font_a.B], st[font_a.I], st[font_a.U]);
}

int main()
{
    char ch;
    Print();
    puts("f)change font    s)change size    a)change alignment");
    puts("b)toggle bold    i)toggle italic  u)toggle underline");
    puts("q)quit");
    while ((ch = getchar()) == '\n');//这样处理就没出错了- - 
    while(ch != 'q')
    {
        getchar();
        switch (ch)
        {
            case 'f':
                funcf();
                break;
            case 's':
                funcs();
                break;
            case 'a':
                funca();
                break;
            case 'b':
                funcb();
                break;
            case 'i':
                funci();
                break;
            case 'u':
                funcu();
                break;
            default:
                break;
        }
        Print();
        puts("f)change font    s)change size    a)change alignment");
        puts("b)toggle bold    i)toggle italic  u)toggle underline");
        puts("q)quit");
        while ((ch = getchar()) == '\n');
    }

}

猜你喜欢

转载自blog.csdn.net/asdgyy/article/details/82966762