C Primer Plus 第15章 位操作 复习题与编程练习

C Primer Plus 第15章 位操作 复习题与编程练习
复习题
1、将下列十进制数转换为二进制形式:
a. 3
b. 13
c. 59
d. 119
答:
a. 11
b. 1101
c. 111011
d. 1110111

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
d. 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
c. 0
d. 1
e. 6
f. 1
g. 40

5、因为ASCII码仅使用最后的7位,所以有时需要屏蔽掉其他位。相应的二进制掩码是什么?分别以十进制、八进制和十六进制形式如何表示这个掩码?
答:掩码在二进制中为1111111。它的十进制表示为127,八进制表示为0177,十六进制表示为0x7F。

6、在程序清单15.2中,可以做以下替换,把:
while(bits-- > 0)
{
    mask |= bitval;
    bitval <<= 1;
}
用:
while(bits-- > 0)
{
    mask |= bitval;
    bitval *= 2;
}
替换,而程序仍将工作。这是否意味着*= 2等同于<<= 1?|=和+=又怎样?
答:
bitval *= 2和bitval << 1都把bitval的当前值加倍,所以他们是等效的。但是mask += bitval和mask |= bitval只有在bitval和mask没有同时设置为打开的位时才具有相同的效果。例如,2 | 4 = 6,但是3 | 6  = 7。

7、
a. Tinkerbell计算机有一个硬件字节,可以将该字节读入程序。该字节包括下列信息:
含义
0到1 1.4MB软盘驱动器数量
2 未使用
3到4 CD-ROM驱动器数量
5 未使用
6到7 硬盘驱动器数量
Tinkerbell和IBM PC一样从右到左填充结构位字段。创建一个适于存放该信息的位字段模板。
b. Klinkerbell与Tinkerbell类似,但它从左到右填充结构。请为Klinkerbell创建相应的位字段模板。
答:
a.
struct tinkerbell {
    unsigned  int diskdrivers   : 2;
    unsigned  int                    : 1;
    unsigned  int cdromdrivers: 2;
    unsigned  int                    : 1;
    unsigned  int harddrivers  : 2;
};
b.
struct klinkerbell {
    unsigned  int harddrivers  : 2;
    unsigned  int                    : 1;
    unsigned  int cdromdrivers: 2;
    unsigned  int                    : 1;
    unsigned  int diskdrivers   : 2;
};

编程练习
1、
#include <stdio.h>
#include < string.h>
#include <math.h>
int stoi( char *);
int main( void)
{
     char pbin[9];
    printf("请输入一个(8位)二进制字符串:\n");
    puts("在一行开始处键入[Enter]结束循环:");
     while(fgets(pbin, 9, stdin) != NULL && pbin[0] != '\n')
    {
        printf("二进制序列%s转换为十进制数为: %d\n", pbin, stoi(pbin));
         while(getchar() != '\n')
             continue;
        printf("请输入一个二进制字符串:\n");
    }
    printf("Bye!\n");
     return 0;
}
int stoi( char * s)
{
     int len = strlen(s);
    unsigned  int tot = 0;

     for( int i = 0; i < len; i++)
         if(s[i] == '1')
            tot += pow(2, len - 1 - i);
     return tot;
}
看看别人写的代码(借鉴h ttp://ptgmedia.pearsoncmg.com/images/9780321928429/downloads/9780321928429_ProgrammingExerciseAnswers_Selected.pdf)
即优美又考虑周全,要学习!!!
#include <stdio.h>
#include <stdbool.h>
#include <limits.h>   //  for CHAR_BIT 一个char的位数
#include < string.h>

int bstr_to_dec( const  char * str);
bool check_val( const  char * str);
char * s_gets( char * st,  int n);
int main( void)
{
     const size_t SLEN = CHAR_BIT *  sizeof( int) + 1;
     char value[SLEN];

    printf("Enter a binary number with up to %zu digits: ", SLEN - 1);
     while(s_gets(value, SLEN) != NULL && value[0] != '\0')
    {
         if(!check_val(value))
            puts("A binary number contains just 0s and 1s.");
         else
            printf("%s is %d\n", value, bstr_to_dec(value));
        puts("Enter next number (empty line to quit): ");
    }
    puts("Done");
     return 0;
}
bool check_val( const  char * str)
{
     bool valid =  true;

     while(valid && *str != '\0')
    {
         if(*str != '0' && *str != '1')
            valid =  false;
        str++;
    }
     return valid;
}
int bstr_to_dec( const  char * str)
{
     int val = 0;

     while(*str != '\0')
         val  =  2  *  val  +  ( * str ++  -  ' 0 ' );   //  二进制——>十进制太神奇了
     return val;
}
char * s_gets( char * st,  int n)
{
     char * ret_val;
     char * find;

    ret_val = fgets(st, n, stdin);
     if(ret_val)
    {
        find = strchr(ret_val, '\n');
         if(find)
            *find = '\0';
         else
             while(getchar() != '\n')
                continue;
    }
     return ret_val;
}

2、
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <limits.h>   //  for CHAR_BIT 一个char的位数
#include < string.h>

int bstr_to_dec( const  char * str);
char * itobs( int n,  char * ps);
void show_bstr( const  char * str);

int main( int argc,  char *argv[])
{
     const size_t SLEN = CHAR_BIT *  sizeof( int) + 1;
     char bin_str[SLEN];
     int value0, value1, value3;

     if(argc != 3)
    {
        printf("输入格式错误!\n");
        printf("请按照\"%s 字符串 字符串\"格式输入\n");
        exit(1);
    }
    value0 = bstr_to_dec(argv[1]);
    value1 = bstr_to_dec(argv[2]);
    printf("~%s = ", argv[1]);
    show_bstr(itobs(~value0, bin_str));
    printf("\n~%s = ", argv[2]);
    show_bstr(itobs(~value1, bin_str));
    value3 = value0 & value1;
    printf("\n%s & %s = ", argv[1], argv[2]);
    show_bstr(itobs(value3, bin_str));
    value3 = value0 | value1;
    printf("\n%s | %s = ", argv[1], argv[2]);
    show_bstr(itobs(value3, bin_str));
    value3 = value0 ^ value1;
    printf("\n%s ^ %s = ", argv[1], argv[2]);
    show_bstr(itobs(value3, bin_str));

     return 0;
}
int bstr_to_dec( const  char * str)
{
     int val = 0;

     while(*str != '\0')
        val = 2 * val + (*str++ - '0');   //  二进制——>十进制太神奇了
     return val;
}
char * itobs( int n,  char * ps)
{
     int i;
     static  int size = CHAR_BIT *  sizeof( int);

     for(i = size - 1; i >= 0; i--, n >>= 1)
        ps[i] = (01 & n) + '0';
    ps[size] = '\0';

     return ps;
}
/*  4位一组显示二进制字符串  */
void show_bstr( const  char * str)
{
     int i = 0;

     while(str[i])
    {
        putchar(str[i]);
         if(++i % 4 == 0 && str[i])
            putchar(' ');
    }
}
运行结果图:


3、
#include <stdio.h>
#include <limits.h>   //  for CHAR_BIT 一个char的位数

char * itobs( int n,  char * ps);
int get_count( const  char *);

int main( void)
{
     const size_t SLEN = CHAR_BIT *  sizeof( int) + 1;
     char bin_str[SLEN];
     int number, count;

    puts("请输入一个整数: ");
     while(scanf("%d", &number) == 1)
    {
        count = get_count(itobs(number, bin_str));
        printf("%d这个数中打开的位的数量: %d\n", number, count);
        puts("请输入一个整数: ");
    }
    puts("Bye!");
     return 0;
}
char * itobs( int n,  char * ps)
{
     int i;
     static  int size = CHAR_BIT *  sizeof( int);

     for(i = size - 1; i >= 0; i--, n >>= 1)
        ps[i] = (01 & n) + '0';
    ps[size] = '\0';

     return ps;
}
int get_count( const  char * ps)
{
     int count = 0;

     while(*ps != '\0')
         if(*ps++ == '1')
            count++;
     return count;
}

4、
#include <stdio.h>
#include <limits.h>   //  for CHAR_BIT 一个char的位数

int fun_itobs( int n,  int index);

int main( void)
{
     int number, count;

    puts("请输入一个整数: ");
     while(scanf("%d", &number) == 1)
    {
        puts("请输入一个位的位置: ");
         while(scanf("%d", &count) != 1 || count < 0 || count > 31)
        {
            printf("您输入的不是一个数字,或者范围不在%d到%d之间\n", 0, CHAR_BIT *  sizeof( int) - 1);
            printf("请您重新输入: \n");
             while(getchar() != '\n')
                 continue;
        }
         if(fun_itobs(number, count))
            printf("%d在位%d上的值是1\n", number, count);
         else
            printf("%d在位%d上的值是0\n", number, count);
        puts("请输入一个整数: ");
    }
    puts("Bye!");
     return 0;
}
int fun_itobs( int n,  int index)
{
     int i, ret_val;
     static  int size = CHAR_BIT *  sizeof( int);
     char ps[size + 1];

     for(i = size - 1; i >= 0; i--, n >>= 1)
        ps[i] = (01 & n) + '0';
    ps[size] = '\0';

     if(ps[size - 1 - index] == '1')
        ret_val = 1;
     else
        ret_val = 0;

     return ret_val;
}

5、(借鉴h ttp://ptgmedia.pearsoncmg.com/images/9780321928429/downloads/9780321928429_ProgrammingExerciseAnswers_Selected.pdf的做法,因为实在没想到)
#include <stdio.h>
#include <limits.h>   //  for CHAR_BIT 一个char的位数

char * itobs( int n,  char * ps);
unsigned  int rotate_1(unsigned  int, unsigned  int);

int main( void)
{
     char bin_str1[CHAR_BIT *  sizeof( int) + 1];
     char bin_str2[CHAR_BIT *  sizeof( int) + 1];
    unsigned  int number, count, result;

    printf("Enter an integer (q to quit): \n");
     while(scanf("%d", &number))
    {
        printf("Enter the number of bits to be rotated: \n");
         if(scanf("%d", &count) != 1)
             break;
        result = rotate_1(number, count);
        itobs(number, bin_str1);
        itobs(result, bin_str2);
        printf("%u rotated is %u.\n", number, result);
        printf("%s rotated is %s.\n", bin_str1, bin_str2);
        printf("Enter an integer (q to quit): \n");
    }
    puts("Bye!");
     return 0;
}
char * itobs( int n,  char * ps)
{
     int i;
     const  static  int size = CHAR_BIT *  sizeof( int);

     for(i = size - 1; i >= 0; i--, n >>= 1)
        ps[i] = (01 & n) + '0';
    ps[size] = '\0';

     return ps;
}
unsigned  int rotate_1(unsigned  int n, unsigned  int b)
{

     static  const  int size = CHAR_BIT *  sizeof( int);
    unsigned  int overflow;

    b %= size;
    overflow = n >> (size - b);
     return (n << b) | overflow;   //  没想到这点
}

6、(全部是自己写的,完美实现!!!)
#include <stdio.h>
#include < string.h>
/*  字体是否粗体  */
#define BOLD_ON 1
#define BOLD_OFF 0
/*  字体对齐方式  */
#define LEFT 0
#define RIGHT 1
#define CENTER 2
/*  字体是否斜体  */
#define ITALIC_ON 1
#define ITALIC_OFF 0
/*  字体是否有下划线  */
#define UNDERLINE_ON 1
#define UNDERLINE_OFF 0
#define MASK 0xFFFFFF00
#define MASK1 0xFFFF80FF

struct font {
    unsigned  int font_id    : 8;
    unsigned  int font_size  : 7;
    unsigned  int            : 1;
    unsigned  int alignment  : 2;
    unsigned  int bold       : 1;
    unsigned  int italic     : 1;
    unsigned  int underline  : 1;
    unsigned  int            : 3;
};
void show( const  struct font * ft);
int getlet( const  char *);
int getmenu( void);
void eatline( void);

int main( void)
{
     /*  初始化font结构  */
     struct font ft = {1, 12, LEFT, BOLD_OFF, ITALIC_OFF, UNDERLINE_OFF};
     int choice;
     int id, size, align;
    show(&ft);
    putchar('\n');
     while((choice = getmenu()) != 'q')
    {
         switch(choice)
        {
             case 'f': printf("Enter font id (0-255): ");
                       while(scanf("%d", &id) != 1 || id < 0 || id > 255)
                      {
                          printf("您输入的不是一个整数,或者范围不在0到255之间\n");
                           while(getchar() != '\n');
                               continue;
                          printf("Enter font id (0-255): ");
                      }
                      eatline();
                      ft.font_id = (ft.font_id & MASK) | id;
                      putchar('\n');
                      show(&ft);
                       break;
             case 's': printf("Enter font size (0-127): ");
                       while(scanf("%d", &size) != 1 || size < 0 || size > 255)
                      {
                          printf("您输入的不是一个整数,或者范围不在0到127之间\n");
                           while(getchar() != '\n');
                               continue;
                          printf("Enter font size (0-127): ");
                      }
                      eatline();
                      ft.font_size = ((ft.font_size & MASK1) >> 8) | size;
                      putchar('\n');
                      show(&ft);
                       break;
             case 'a': printf("Select alignment: \n");
                      puts("l) left c) center r)right");
                      align = getlet("lcr");
                       switch(align)
                      {
                            case 'l': ft.alignment = LEFT;
                                      break;
                            case 'c': ft.alignment = CENTER;
                                      break;
                            case 'r': ft.alignment = RIGHT;
                                      break;
                      }
                      putchar('\n');
                      show(&ft);
                       break;
             case 'b': ft.bold = BOLD_ON;
                      putchar('\n');
                      show(&ft);
                       break;
             case 'i': ft.italic = ITALIC_ON;
                      putchar('\n');
                      show(&ft);
                       break;
             case 'u': ft.underline = UNDERLINE_ON;
                      putchar('\n');
                      show(&ft);
                       break;
        }
    }
    puts("Bye!");

     return 0;
}
void show( const  struct font * ft)
{
    printf("ID\tSIZE\tALIGNMENT\tB\tI\tU\n");
    printf("%d\t%d", ft->font_id, ft->font_size);
     switch(ft->alignment)
    {
         case LEFT: printf("%10s", "left");
                    break;
         case RIGHT: printf("%10s", "right");
                     break;
         case CENTER: printf("%10s", "center");
                      break;
         default: printf("unknown alignment");
    }
    printf("%14s%8s%8s\n", ft->bold == BOLD_OFF? "off" : "on",
                           ft->italic == ITALIC_OFF? "off" : "on",
                           ft->underline == UNDERLINE_OFF? "off" : "on");
}
int getlet( const  char * s)
{
     char c;

    c = getchar();
     while(strchr(s, c) == NULL)
    {
        printf("请您在%s这串字符串中输入一个字符: \n", s);
         while(getchar() != '\n')
             continue;
        c = getchar();
    }
     while(getchar() != '\n')
         continue;
     return c;
}
int getmenu( void)
{
     int i;

     const  char * str[7] = {
        "change font",
        "change size",
        "change alignment",
        "toggle bold",
        "toggle italic",
        "toggle underline",
        "quit"
    };
     const  char pstr[8] = "fsabiuq";

     for(i = 0; i < 7; i++)
    {
        printf("%c) %s   ", pstr[i], str[i]);
         if(i % 3 == 2)
            putchar('\n');
    }
     if(i % 3 != 0)
        putchar('\n');

     return getlet(pstr);
}
void eatline( void)
{
     while(getchar() != '\n')
         continue;
}

7、(有大问题,明天再看!!!借鉴 h ttp://ptgmedia.pearsoncmg.com/images/9780321928429/downloads/9780321928429_ProgrammingExerciseAnswers_Selected.pdf但是程序也有问题)
#include <stdio.h>
#include < string.h>
#include <ctype.h>

#define LEFT 0x00000
#define CENTER 0x08000
#define RIGHT 0x10000
#define BOLD 0x20000
#define UNDERLINE 0x80000
#define ID_MASK 0xFF
#define SIZE_MASK 0x7F00
#define ALIGN_MASK 0x18000

#define ITALIC 0x40000
#define SIZE_SHIFT 8

typedef unsigned  long font;

char do_menu(font * f);    //  f为一个指向unsigned long的指针
void show_font(font f);
char get_choice( const  char *);
void show_menu( void);
void eatline( void);
void get_id(font * f);
void get_size(font * f);
void get_align(font * f);

int main( void)
{
    font sample = 1 | (12 << SIZE_SHIFT) | LEFT | ITALIC;  //  sample = 0100 0000 1100 0000 0001(斜体,没有预留空隙)

     while(do_menu(&sample) != 'q')
         continue;
    puts("Bye!");

     return 0;
}
char do_menu(font * f)
{
     char response;

    show_font(*f);
    show_menu();
    response = get_choice("fsabiuq");
     switch(response)
    {
         case 'f': get_id(f);  break;
         case 's': get_size(f);  break;
         case 'a': get_align(f);  break;
         case 'b': *f ^= BOLD;  break;
         case 'i': *f ^= ITALIC;  break;
         case 'u': *f ^= UNDERLINE;  break;
         case 'q':  break;
         default: printf("menu problem\n");
    }
     return response;
}
void show_font(font f)
{
    printf("\n%4s %4s %9s %3s %3s %3s\n", "ID", "SIZE", "ALIGNMENT", "B", "I", "U");
    printf("%4lu %4lu", f & ID_MASK, (f & SIZE_MASK) >> SIZE_SHIFT);
     switch(f & ALIGN_MASK)
    {
         case LEFT: printf("%7s", "left");  break;
         case CENTER: printf("%7s", "center");  break;
         case RIGHT: printf("%7s", "right");  break;
         default: printf("%7s", "known");  break;
    }
    printf("%8s %3s %3s\n\n", (f & BOLD) == BOLD ? "on" : "off",
                              (f & ITALIC) == ITALIC ? "on" : "off",
                              (f & UNDERLINE) == UNDERLINE ? "on" : "off");
}
char get_choice( const  char * s)
{
     char ch;

    ch = getchar();
    ch = tolower(ch);

     while(strchr(s, ch) == NULL)
    {
        printf("Please enter one of the following: %s\n", s);
        eatline();
        ch = tolower(getchar());
    }
    eatline();
     return ch;
}
void eatline( void)
{
     while(getchar() != '\n')
         continue;
}
void show_menu( void)
{
    puts("f) change font   s) change size     a) change alignment");
    puts("b) toggle bold   i) toggle italic   u) toggle underline");
    puts("q) quit");
}
void get_id(font * f)
{
     int id;

    printf("Enter font id (0-255): ");
    scanf("%d", &id);
    id = id & ID_MASK;
     // *f |= id;
    *f = (*f & 0xFFF00) | id;   //  相应位要先置为0之后再用|运算符吧!!!( 问题出现在这)
    eatline();
}
void get_size(font * f)
{
     int size;

    printf("Enter font size (0-127): ");
    scanf("%d", &size);
    *f &= (0xF8011);
    *f |= (size << SIZE_SHIFT) & SIZE_MASK;
    eatline();
}
void get_align(font * f)
{
    printf("Select alignment: \n");
    printf("l) left  c) center  r) right\n");
     switch(get_choice("lcr"))
    {
         case 'l': *f &= ~ALIGN_MASK;
                  *f |= LEFT;
                   break;
         case 'c': *f &= ~ALIGN_MASK;
                  *f |= CENTER;
                   break;
         case 'r': *f &= ~ALIGN_MASK;
                  *f |= RIGHT;
                   break;
         default: printf("alignment problem\n");
    }
}



你可能感兴趣的:(C Primer Plus 第15章 位操作 复习题与编程练习)