当前位置:   article > 正文

第十五章 位操作_btoi

btoi
  • 按位取反运算符:~,作用:将对应二进制码取反。代码示例example.c:

  1. #include <stdio.h>
  2. int main(void)
  3. {
  4. unsigned char val = 2; // 00000010
  5. unsigned char new_val = ~val; // 11111101
  6. printf("Now val is %d\n", val);
  7. printf("Now new_val is %d\n", new_val);
  8. return 0;
  9. }
'
运行

输出结果:

  • 按位与运算符:&,作用:两个二进制位都为真时取真。代码示例example.c :

  1. #include <stdio.h>
  2. int main(void)
  3. {
  4. unsigned char var1 = 0x93; // 147 10010011
  5. unsigned char var2 = 0x3d; // 61 00111101
  6. unsigned char var3 = var1 & var2; //0x11 17 00010001
  7. printf("var1 is %d\n", var1);
  8. printf("var2 is %d\n", var2);
  9. printf("var3 is %d\n", var3);
  10. var1 &= var2; //Equal to var1 = var1 & var2;
  11. printf("Now var1 is %d\n", var1);
  12. return 0;
  13. }
'
运行

输出结果:

  • 按位或运算符:|,作用:当两个二进制位有一个为真时取真。代码示例example.c:

  1. #include <stdio.h>
  2. int main(void)
  3. {
  4. unsigned char var1 = 0x93; // 10010011 147
  5. unsigned char var2 = 0x3d; // 00111101 61
  6. unsigned char var3 = var1 | var2; // 10111111 0xbf 191
  7. printf("var1 = %d\n", var1);
  8. printf("var2 = %d\n", var2);
  9. printf("var3 = %d\n", var3);
  10. var1 |= var2; // Equal to var1 = var1 | var2
  11. printf("Now var1 = %d\n", var1);
  12. return 0;
  13. }

输出结果:

  • 按位异或运算符:^,作用:当且仅当两个二进制位中仅有一个为真时取真。代码示例example.c:

  1. #include <stdio.h>
  2. int main(void)
  3. {
  4. unsigned char var1 = 0x93; // 10010011 147
  5. unsigned char var2 = 0x3d; // 00111101 61
  6. unsigned char var3 = var1 ^ var2; // 10101110 0xae 174
  7. printf("var1 = %d\n", var1);
  8. printf("var2 = %d\n", var2);
  9. printf("var3 = %d\n", var3);
  10. var1 ^= var2; // Equal to var1 = var1 ^ var2;
  11. printf("Now var1 = %d\n", var1);
  12. return 0;
  13. }

输出结果:

  • 左移运算符:<<,作用:将其左侧运算对象每一位的值向左移动其右侧运算对象指定的位数,左侧运算对象移除左末端位的值丢失,用0填充空出的位置。示例代码:example.c

  1. #include <stdio.h>
  2. int main(void)
  3. {
  4. int stonk = 1; // 00000001
  5. int onkoo;
  6. onkoo = stonk << 2; // 00000100
  7. stonk <<= 2;
  8. printf("onkoo = %d\n", onkoo);
  9. printf("stonk = %d\n", stonk);
  10. return 0;
  11. }
'
运行

输出结果:

  • 右移运算符:>>,作用:将其左侧运算对象每一位的值向右移动其右侧运算对象指定的位数,左侧运算对象移除右末端位的值丢失,对于有符号类型,取决于机器用0或者1填充空出的位置,对于无符号类型,都用0填充空出的位置。示例代码example.c:

  1. #include <stdio.h>
  2. int main(void)
  3. {
  4. signed char var1 = 0x8a; // 10001010 -(256-138) = -118
  5. signed char var2 = var1 >> 2; // 11100010 -(256 - 0xe2) = -(256-226) = -30
  6. unsigned char var3 = 0x8a >> 2; // 00100010 0x22 34
  7. printf("var1 = %d\n", var1);
  8. printf("var2 = %d\n", var2);
  9. printf("var3 = %d\n", var3);
  10. return 0;
  11. }

输出结果:

  • 程序清单15.1,binbit.c:

  1. /*binbit.c -- 使用位操作显示二进制 */
  2. #include <stdio.h>
  3. #include <limits.h> //提供 CHAR_BIT 的定义,CHAR_BIT 表示每字节的位数
  4. char * itobs(int, char *);
  5. void show_bstr(const char *);
  6. int main(void)
  7. {
  8. char bin_str[CHAR_BIT * sizeof(int) + 1];
  9. int number;
  10. puts("Enter integers and see them in binary.");
  11. puts("Non-numeric input terminates program.");
  12. while (scanf("%d", &number) == 1)
  13. {
  14. itobs(number, bin_str);
  15. printf("%d is ", number);
  16. show_bstr(bin_str);
  17. putchar('\n');
  18. }
  19. puts("Bye!");
  20. return 0;
  21. }
  22. char * itobs(int n, char * ps)
  23. {
  24. int i;
  25. static const int size = CHAR_BIT * sizeof(int);
  26. for (i = size - 1; i >= 0; i--, n >>=1) // 7 -> 0000 0111
  27. ps[i] = (01 & n) + '0'; // 0000 0001
  28. ps[size] = '\0';
  29. return ps;
  30. }
  31. void show_bstr(const char * str)
  32. {
  33. int i = 0;
  34. while(str[i])
  35. {
  36. putchar(str[i]);
  37. if (++i % 4 == 0 && str[i])
  38. putchar(' ');
  39. }
  40. }

输出结果:

  • 程序清单15.2, invert4.c:

  1. /*invert4.c -- 使用位操作显示二进制 */
  2. #include <stdio.h>
  3. #include <limits.h> //提供 CHAR_BIT 的定义,CHAR_BIT 表示每字节的位数
  4. char * itobs(int, char *);
  5. void show_bstr(const char *);
  6. int invert_end(int num, int bits);
  7. int main(void)
  8. {
  9. char bin_str[CHAR_BIT * sizeof(int) + 1];
  10. int number;
  11. puts("Enter integers and see them in binary.");
  12. puts("Non-numeric input terminates program.");
  13. while (scanf("%d", &number) == 1)
  14. {
  15. itobs(number, bin_str);
  16. printf("%d is ", number);
  17. show_bstr(bin_str);
  18. putchar('\n');
  19. number = invert_end(number, 4);
  20. printf("Inverting the last 4 bits gives\n");
  21. show_bstr(itobs(number, bin_str));
  22. putchar('\n');
  23. }
  24. puts("Bye!");
  25. return 0;
  26. }
  27. char * itobs(int n, char * ps)
  28. {
  29. int i;
  30. static const int size = CHAR_BIT * sizeof(int);
  31. for (i = size - 1; i >= 0; i--, n >>= 1) // 7 -> 0000 0111
  32. ps[i] = (01 & n) + '0'; // 0000 0001
  33. ps[size] = '\0';
  34. return ps;
  35. }
  36. void show_bstr(const char * str)
  37. {
  38. int i = 0;
  39. while(str[i])
  40. {
  41. putchar(str[i]);
  42. if (++i % 4 == 0 && str[i])
  43. putchar(' ');
  44. }
  45. }
  46. int invert_end(int num, int bits)
  47. {
  48. int mask = 0;
  49. int bitval = 1;
  50. while (bits-- > 0)
  51. {
  52. mask |= bitval;
  53. bitval <<= 1;
  54. }
  55. return num ^ mask;
  56. }
'
运行

输出结果:

  • 程序清单15.3,fields.c:

  1. /* fields.c -- 定义并使用字段 */
  2. #include <stdio.h>
  3. #include <stdbool.h>
  4. /* 线的样式 */
  5. #define SOLID 0
  6. #define DOTTED 1
  7. #define DASHED 2
  8. /* 三原色 */
  9. #define BLUE 4
  10. #define GREEN 2
  11. #define RED 1
  12. /* 混合色 */
  13. #define BLACK 0
  14. #define YELLOW (RED | GREEN)
  15. #define MAGENTA (RED | BLUE)
  16. #define CYAN (GREEN | BLUE)
  17. #define WHITE (RED | GREEN | BLUE)
  18. const char * colors[8] = { "black", "red", "green", "yellow",
  19. "blue", "magenta", "cyan", "white" };
  20. struct box_props {
  21. bool opaque : 1;
  22. unsigned int fill_color : 3;
  23. unsigned int : 4;
  24. bool show_border : 1;
  25. unsigned int border_color : 3;
  26. unsigned int border_style : 2;
  27. unsigned int : 2;
  28. };
  29. void show_settings(const struct box_props * pb);
  30. int main(void)
  31. {
  32. /* 创建并使用 box_props 结构 */
  33. struct box_props box = { true, YELLOW, true, GREEN, DASHED };
  34. printf("Original box settings:\n");
  35. show_settings(&box);
  36. box.opaque = false;
  37. box.fill_color = WHITE;
  38. box.border_color = MAGENTA;
  39. box.border_style = SOLID;
  40. printf("\nModified box settings:\n");
  41. show_settings(&box);
  42. return 0;
  43. }
  44. void show_settings(const struct box_props * pb)
  45. {
  46. printf("Box is %s.\n", pb->opaque == true ? "opaque" : "transparent");
  47. printf("The fill color is %s.\n", colors[pb->fill_color]);
  48. printf("Border %s.\n", pb->show_border == true ? "shown" : " not shown");
  49. printf("The border color is %s.\n", colors[pb->border_color]);
  50. printf("The border style is ");
  51. switch (pb->border_style)
  52. {
  53. case SOLID: printf("solid.\n"); break;
  54. case DOTTED: printf("dotted.\n"); break;
  55. case DASHED: printf("dashed.\n"); break;
  56. default: printf("unknown type.\n");
  57. }
  58. }
'
运行

输出结果:

  • 程序清单15.4, dualview.c:

  1. /* dualview.c -- 位字段和按位运算符 */
  2. #include <stdio.h>
  3. #include <stdbool.h>
  4. #include <limits.h>
  5. /* 位字段符号常量 */
  6. /* 边框线样式 */
  7. #define SOLID 0
  8. #define DOTTED 1
  9. #define DASHED 2
  10. /* 三原色 */
  11. #define BLUE 4
  12. #define GREEN 2
  13. #define RED 1
  14. /* 混合色 */
  15. #define BLACK 0
  16. #define YELLOW (RED | GREEN)
  17. #define MAGENTA (RED | BLUE)
  18. #define CYAN (GREEN | BLUE)
  19. #define WHITE (RED | GREEN | BLUE)
  20. /* 按位方法用到的符号常量 */
  21. #define OPAQUE 0x1
  22. #define FILL_BLUE 0x8
  23. #define FILL_GREEN 0x4
  24. #define FILL_RED 0x2
  25. #define FILL_MASK 0xE
  26. #define BORDER 0x100
  27. #define BORDER_BLUE 0x800
  28. #define BORDER_GREEN 0x400
  29. #define BORDER_RED 0x200
  30. #define BORDER_MASK 0xE00
  31. #define B_SOLID 0
  32. #define B_DOTTED 0x1000
  33. #define B_DASHED 0x2000
  34. #define STYLE_MASK 0x3000
  35. const char * colors[8] = { "black", "red", "green", "yellow", "blue", "magenta",
  36. "cyan", "white" };
  37. struct box_props {
  38. bool opaque : 1;
  39. unsigned int fill_color : 3;
  40. unsigned int : 4;
  41. bool show_border : 1;
  42. unsigned int border_color : 3;
  43. unsigned int border_style : 2;
  44. unsigned int : 2;
  45. };
  46. union Views /* 把数据看作结构或 unsigned short 类型的变量 */
  47. {
  48. struct box_props st_view;
  49. unsigned short us_view;
  50. };
  51. void show_settings(const struct box_props * pb);
  52. void show_settings1(unsigned short);
  53. char * itobs(int n, char * ps);
  54. int main(void)
  55. {
  56. /* 创建 Views 联合,并初始化initialize struct box view */
  57. union Views box = { { true, YELLOW, true, GREEN, DASHED } };
  58. char bin_str[8 * sizeof(unsigned int) + 1];
  59. printf("Original box settings:\n");
  60. show_settings(&box.st_view);
  61. printf("\nBox settings using unsigned int view:\n");
  62. show_settings1(box.us_view);
  63. printf("bits are %s\n", itobs(box.us_view, bin_str));
  64. box.us_view &= ~FILL_MASK; /* 把表示填充色的位清0 */
  65. box.us_view |= (FILL_BLUE | FILL_GREEN); /* 重置填充色 */
  66. box.us_view ^= OPAQUE; /* 切换是否透明的位 */
  67. box.us_view |= BORDER_RED; /* 错误的方法 */
  68. box.us_view &= ~STYLE_MASK;/* 把样式的位清0 */
  69. box.us_view |= B_DOTTED; /* 把样式设置为点 */
  70. printf("\nModified box settings:\n");
  71. show_settings(&box.st_view);
  72. printf("\nBox settings using unsigned int view:\n");
  73. show_settings1(box.us_view);
  74. printf("bits are %s\n", itobs(box.us_view, bin_str));
  75. return 0;
  76. }
  77. void show_settings(const struct box_props * pb)
  78. {
  79. printf("Box is %s.\n", pb->opaque == true ? "opaque" : "transparent");
  80. printf("The fill color is %s.\n", colors[pb->fill_color]);
  81. printf("Border %s.\n", pb->show_border == true ? "shown" : " not shown");
  82. printf("The border color is %s.\n", colors[pb->border_color]);
  83. printf("The border style is ");
  84. switch (pb->border_style)
  85. {
  86. case SOLID : printf("solid.\n"); break;
  87. case DOTTED: printf("dotted.\n"); break;
  88. case DASHED: printf("dashed.\n"); break;
  89. default : printf("unknown type.\n");
  90. }
  91. }
  92. void show_settings1(unsigned short us)
  93. {
  94. printf("box is %s.\n", (us & OPAQUE) == OPAQUE ? "opaque" : "transparent");
  95. printf("The fill color is %s.\n", colors[(us >> 1) & 07]);
  96. printf("Border %s.\n", (us & BORDER) == BORDER ? "shown" : "not shown");
  97. printf("The border style is ");
  98. switch (us & STYLE_MASK)
  99. {
  100. case B_SOLID : printf("solid.\n"); break;
  101. case B_DOTTED : printf("dotted.\n"); break;
  102. case B_DASHED : printf("dashed.\n"); break;
  103. default : printf("unknow type.\n");
  104. }
  105. printf("The border color is %s.\n", colors[(us >> 9) & 07]);
  106. }
  107. char * itobs(int n, char * ps)
  108. {
  109. int i;
  110. static const int size = CHAR_BIT * sizeof(int);
  111. for (i = size - 1; i >= 0; i--, n >>=1) // 7 -> 0000 0111
  112. ps[i] = (01 & n) + '0'; // 0000 0001
  113. ps[size] = '\0';
  114. return ps;
  115. }

输出结果:

  • 程序清单15.5,align.c:

  1. /* align.c -- 使用 _Alignof 和 _Alignas (C!!) */
  2. #include <stdio.h>
  3. int main(void)
  4. {
  5. double dx;
  6. char ca;
  7. char cx;
  8. double dz;
  9. char cb;
  10. char _Alignas(double) cz;
  11. printf("char alignment: %zd\n", _Alignof(char));
  12. printf("double alignment: %zd\n", _Alignof(double));
  13. printf("&dx: %p\n", &dx);
  14. printf("&ca: %p\n", &ca);
  15. printf("&cx: %p\n", &cx);
  16. printf("&dz: %p\n", &dz);
  17. printf("&cb: %p\n", &cb);
  18. printf("&cz: %p\n", &cz);
  19. return 0;
  20. }

输出结果:

  • 编程练习:

题目1

方法一:使用位操作。代码示例15_1_1.c:

  1. #include <stdio.h>
  2. #include <ctype.h> // 提供 isspace() 函数
  3. #include <string.h> // 提供 strchr() 函数
  4. #define SIZE 50
  5. int get_bstr(char * st, int n);
  6. char * del_space(char * st);
  7. int btoi(char * st);
  8. int main(void)
  9. {
  10. char binstr[SIZE];
  11. int number;
  12. printf("Please input a binary string, [Enter] to quit: ");
  13. while(get_bstr(binstr, SIZE))
  14. {
  15. number = btoi(del_space(binstr));
  16. printf("Binary string %s is %d in decimal.\n", binstr, number);
  17. printf("Please input another binary string, [Enter] to quit: ");
  18. }
  19. return 0;
  20. }
  21. int get_bstr(char * st, int n) //通过指针获取字符串并返回字符串的长度
  22. {
  23. char ch;
  24. int i;
  25. //获取仅含 0或1 的字符串 ,注意通过 getchar() 获取的是字符而不是数字,加单引号
  26. for (i = 0; i < n - 1 && (ch = getchar()) != '\n' && (ch == '1' || ch == '0'
  27. || isspace(ch)); i++)
  28. st[i] = ch;
  29. st[i] = '\0'; //最后一个字符设为空字符
  30. //处理超出 n的大小的字符
  31. if (ch != '\n')
  32. while (getchar() != '\n')
  33. continue;
  34. return i;
  35. }
  36. char * del_space(char * st) // 删去字符中的空格(指针改变了字符串 st)
  37. {
  38. int i;
  39. char * find = NULL;
  40. while ((find = strchr(st, ' ')))
  41. {
  42. for (i = 0; find[i]; i++) // find[i] Equal to *(find + i)
  43. find[i] = find[i + 1];
  44. }
  45. return st;
  46. }
  47. int btoi(char * st) // 通过按位或运算符生成一个目标数
  48. {
  49. int num = 0;
  50. int i;
  51. for (i = 0; st[i]; i++)
  52. {
  53. num <<= 1; // Equal to num = num << 1
  54. num |= (st[i] - '0'); // Equal to num = num | (st[i] - '0')
  55. }
  56. return num;
  57. }

输出结果:

方法二:直接计算,两种方法。代码示例15_1_2.c:

  1. #include <stdio.h>
  2. #include <string.h> // 提供 strlen() 函数
  3. #define SIZE 50
  4. int btoi(char * st);
  5. int btoi1(char * st);
  6. int main(void)
  7. {
  8. char str[SIZE];
  9. printf("Please input a binary string: ");
  10. gets(str);
  11. printf("Binary string %s is %d in decimal.\n", str, btoi(str));
  12. printf("Binary string %s is %d in deciaml.\n", str, btoi1(str));
  13. return 0;
  14. }
  15. int btoi(char * st)
  16. {
  17. int sum = 0;
  18. while (*st) // 读取字符时从左往右读取,每多读取一个数就增大两倍
  19. {
  20. sum *= 2;
  21. sum += *st - '0';
  22. st++;
  23. }
  24. return sum;
  25. }
  26. int btoi1(char * st) // 从左往右理解二进制字符串,直观理解
  27. {
  28. int sum = 0;
  29. int len = strlen(st);
  30. int i, exp;
  31. for (i = len - 1, exp = 1; i >= 0; i--, exp *= 2)
  32. sum += exp * (st[i] - '0');
  33. return sum;
  34. }

输出结果:

题目2

方法一:先转换为数字,运算完成后再转换为字符,递归实现。代码示例15_2_1.c:

  1. #include <stdio.h>
  2. #include <ctype.h> // 提供 isspace() 函数
  3. #include <string.h> // 提供 strchr() 函数
  4. #include <stdlib.h> // 提供 EXIT_FAILURE
  5. #define SIZE 50
  6. int btoi(char * st);
  7. void print_bstr(unsigned int n);
  8. int main(int argc, char * argv[])
  9. {
  10. int num1, num2;
  11. if (argc != 3)
  12. {
  13. fprintf(stderr, "Usage: %s, binary_str1, binary_str2\n", *argv);
  14. exit(EXIT_FAILURE);
  15. }
  16. num1 = btoi(argv[1]);
  17. num2 = btoi(argv[2]);
  18. printf("num1 = %d\n", num1);
  19. printf("~num1 = %d\n", ~num1);
  20. printf("~%s is ", argv[1]);
  21. print_bstr(~num1);
  22. putchar('\n');
  23. printf("~%s is ", argv[2]);
  24. print_bstr(~num2);
  25. putchar('\n');
  26. printf("%s & %s is ", argv[1], argv[2]);
  27. print_bstr(num1 & num2);
  28. putchar('\n');
  29. printf("%s | %s is ", argv[1], argv[2]);
  30. print_bstr(num1 | num2);
  31. putchar('\n');
  32. printf("%s ^ %s is ", argv[1], argv[2]);
  33. print_bstr(num1 ^ num2);
  34. putchar('\n');
  35. return 0;
  36. }
  37. int btoi(char * st) // 通过按位或运算符生成一个目标数
  38. {
  39. int num = 0;
  40. int i;
  41. for (i = 0; st[i]; i++)
  42. {
  43. num <<= 1; // Equal to num = num << 1
  44. num |= (st[i] - '0'); // Equal to num = num | (st[i] - '0')
  45. }
  46. return num;
  47. }
  48. void print_bstr(unsigned int n) // 以二进制字符格式输出一个数的二进制格式
  49. {
  50. static long loop = 0; // 函数执行期间该值不变
  51. if (!loop && !n)
  52. {
  53. putchar('0');
  54. return;
  55. }
  56. if (n)
  57. {
  58. loop++;
  59. print_bstr(n / 2);
  60. }
  61. else
  62. return;
  63. putchar('0' + (n % 2));
  64. if ((--loop % 4) == 0)
  65. putchar(' ');
  66. }

输出结果:

方法二:先转换为数字,运算完成后再转换为字符,位操作实现。代码示例15_2_1.c:

  1. #include <stdio.h>
  2. #include <stdlib.h> // 提供 EXIT_FAILURE
  3. int bstr_to_dec(const char * str); // 2 进制字符串转换为 10 进制
  4. char *itobs(int n, char *str); // 将一个数转换为 2 进制字符串
  5. int main(int argc, char *argv[])
  6. {
  7. char bstr[8 * sizeof(int) + 1];
  8. if (argc != 3)
  9. {
  10. fprintf(stderr, "Usage: %s binarynum1 binarynum2\n", argv[0]);
  11. exit(EXIT_FAILURE);
  12. }
  13. int v1 = bstr_to_dec(argv[1]);
  14. int v2 = bstr_to_dec(argv[2]);
  15. printf("~%s = %s\n", argv[1], itobs(~v1, bstr));
  16. printf("~%s = %s\n", argv[2], itobs(~v2, bstr));
  17. printf("%s & %s = %s\n", argv[1], argv[2], itobs(v1 & v2, bstr));
  18. printf("%s | %s = %s\n", argv[1], argv[2], itobs(v1 | v2, bstr));
  19. printf("%s ^ %s = %s\n", argv[1], argv[2], itobs(v1 ^ v2, bstr));
  20. return 0;
  21. }
  22. int bstr_to_dec(const char * str)
  23. {
  24. int val = 0;
  25. while (*str)
  26. val = val * 2 + ((*str++) - '0');
  27. return val;
  28. }
  29. char *itobs(int n, char *str)
  30. {
  31. int sz = 8 * sizeof(int);
  32. for (int i = sz - 1; i >= 0; --i, n >>= 1)
  33. str[i] = (n & 1) + '0';
  34. str[sz] = '\0';
  35. return str;
  36. }

输出结果:

方法三:按位直接计算,但该方法不适用于计算取反~。示例代码15_2_3.c:

  1. #include <stdio.h>
  2. #include <stdlib.h> //提供 EXIT_FAILURE
  3. void funca(char *a, char *b); // &运算
  4. void funcb(char *a, char *b); // ^运算
  5. void funcc(char *a, char *b); // |运算
  6. int main(int argc, char **argv)
  7. {
  8. char ch;
  9. if(argc != 4)
  10. {
  11. fprintf(stderr, "Usage:%s [string] [string] [char]\n", argv[0]);
  12. exit(EXIT_FAILURE);
  13. }
  14. ch = argv[3][0];
  15. switch(ch)
  16. {
  17. case '1'://不能用位运算符作为识别符号,不符合命令行格式
  18. funca(argv[1], argv[2]);
  19. break;
  20. case '2':
  21. funcb(argv[1], argv[2]);
  22. break;
  23. case '3':
  24. funcc(argv[1], argv[2]);
  25. break;
  26. default: fprintf(stderr, "Wrong!\n");
  27. break;
  28. }
  29. return 0;
  30. }
  31. void funca(char *a, char *b)
  32. {
  33. while(*a && *b)
  34. {
  35. int x = ((*a) - '0') & ((*b) - '0');
  36. putchar(x + '0');
  37. a++;
  38. b++;
  39. }
  40. putchar('\n');
  41. }
  42. void funcb(char *a, char *b)
  43. {
  44. while(*a && *b)
  45. {
  46. int x = ((*a) - '0') ^ ((*b) - '0');
  47. putchar(x + '0');
  48. a++;
  49. b++;
  50. }
  51. putchar('\n');
  52. }
  53. void funcc(char *a, char *b)
  54. {
  55. while(*a && *b)
  56. {
  57. int x = ((*a) - '0') | ((*b) - '0');
  58. putchar(x + '0');
  59. a++;
  60. b++;
  61. }
  62. putchar('\n');
  63. }

输出结果:

题目3

方法一:直接按位&运算。示例代码15_3_1.c:

  1. #include <stdio.h>
  2. int count_openbit(unsigned int n);
  3. int main(void)
  4. {
  5. int num;
  6. printf("Please input an integer(q to quit): ");
  7. while (scanf("%d", &num))
  8. {
  9. while (getchar() != '\n')
  10. continue;
  11. printf("Here are %d bits opend in %d.\n", count_openbit(num), num);
  12. printf("Please input an integer(q to quit): ");
  13. }
  14. return 0;
  15. }
  16. int count_openbit(unsigned int n)
  17. {
  18. int count = 0;
  19. while (n)
  20. {
  21. count += (n & 1);
  22. n >>= 1;
  23. }
  24. return count;
  25. }

输出结果:

方法二:显示详细信息。示例代码15_3_2.c:

  1. #include <stdio.h>
  2. #define TEST_NUM 9
  3. char * itobs(int n, char *str);
  4. int onbits(int x);
  5. int main(void)
  6. {
  7. int x = TEST_NUM;
  8. char bstr[8 * sizeof(int) + 1];
  9. printf("%d(%s) has %d bit on.\n", x, itobs(x, bstr), onbits(x));
  10. return 0;
  11. }
  12. char *itobs(int n, char *str)
  13. {
  14. int sz = 8 * sizeof(int);
  15. for (int i = sz - 1; i >= 0; --i, n >>= 1)
  16. {
  17. str[i] = (n & 1) + '0';
  18. }
  19. str[sz] = '\0';
  20. return str;
  21. }
  22. int onbits(int x)
  23. {
  24. int sum = 0;
  25. for (int i = 8 * sizeof(int) - 1; i >= 0; --i)
  26. {
  27. sum += (x >> i) & 1;
  28. }
  29. return sum;
  30. }

输出结果:

题目4

方法:移动数的位进行按位与运算,两个函数实现相同的功能。示例代码15_4.c:

  1. #include <stdio.h>
  2. #include <stdbool.h>
  3. #include <stdlib.h>
  4. #define TEST_VALUE 9 // 1001
  5. bool isbit_open(int num, int pos);
  6. bool isbit_open1(int num, int pos);
  7. int main(void)
  8. {
  9. int size = 8 * sizeof(int);
  10. int i;
  11. for (i = 0; i < size; i++)
  12. printf("The %dth of %d is %s.\n", i + 1,
  13. TEST_VALUE, isbit_open(TEST_VALUE, i + 1) ? "opend" : "closed");
  14. return 0;
  15. }
  16. bool isbit_open(int num, int pos)
  17. {
  18. if (pos <= 0)
  19. {
  20. fputs("The position can't be 0.", stderr);
  21. exit(1);
  22. }
  23. return (num & (1 << (pos - 1)));
  24. }
  25. bool isbit_open1(int num, int pos)
  26. {
  27. if (pos <= 0)
  28. {
  29. fputs("The position can't be 0.", stderr);
  30. exit(1);
  31. }
  32. return (num >> (pos - 1)) & 1;
  33. }

函数1或2输出结果:

题目5

方法:循环移动或者直接移动位,两种函数实现功能相同,示例代码15_5.c:

  1. #include <stdio.h>
  2. #include <limits.h> //Support for CHAR_BIT
  3. #define TEST_VALUE 9
  4. char * itobs(int n, char *str);
  5. unsigned int rotate_l(unsigned int num, int bits); // 将数的二进制位向左循环移动指定位
  6. unsigned int rotate_l_2(unsigned int num, int bits);
  7. int main(void)
  8. {
  9. char bstr[CHAR_BIT * sizeof(unsigned int) + 1];
  10. printf("%d in binary is \n%s.\n", TEST_VALUE, itobs(TEST_VALUE, bstr));
  11. printf("After rotate to the left for 4 bits, the number in binary is \n%s.\n",
  12. itobs(rotate_l(TEST_VALUE, 4), bstr));
  13. printf("After rotate to the left for 4 bits, the number in binary is \n%s.\n",
  14. itobs(rotate_l_2(TEST_VALUE, 4), bstr));
  15. return 0;
  16. }
  17. char *itobs(int n, char *str)
  18. {
  19. int sz = CHAR_BIT * sizeof(int);
  20. for (int i = sz - 1; i >= 0; --i, n >>= 1)
  21. str[i] = (n & 1) + '0';
  22. str[sz] = '\0';
  23. return str;
  24. }
  25. unsigned int rotate_l(unsigned int num, int bits)
  26. {
  27. int i;
  28. for (i = 0; i < bits; i++) // 先保存最左侧的一位,再将数向右移动1位并或运算,如此循环
  29. num = (num >> (CHAR_BIT * sizeof(unsigned int) - 1)) | (num << 1);
  30. return num;
  31. }
  32. unsigned int rotate_l_2(unsigned int num, int bits)
  33. {
  34. static const int size = CHAR_BIT * sizeof(unsigned int);
  35. bits %= size;
  36. return (num << bits) | (num >> (size - bits));
  37. }
'
运行

输出结果:

题目6

方法:直接更改结构体中的内容即可。示例代码15_6.c:

  1. #include <stdio.h>
  2. #include <ctype.h> // 提供 isspace() 函数
  3. #include <string.h> // 提供 strchr() 函数
  4. typedef unsigned int uint;
  5. typedef struct
  6. {
  7. uint id : 8;
  8. uint sz : 7;
  9. uint at : 2;
  10. uint b : 1;
  11. uint i : 1;
  12. uint u : 1;
  13. } font;
  14. static font ft = { 1, 12, 0, 0, 0, 0 };
  15. const char * state[4] = { "off", "on" };
  16. const char * alignment[7] = { "left", "center", "right" };
  17. void eatline(void);
  18. int get_first(void);
  19. int get_choice(void);
  20. void change_font(void);
  21. void change_size(void);
  22. void change_alignment(void);
  23. void change_toggle(int ch);
  24. int main(void)
  25. {
  26. int ch;
  27. while ((ch = get_choice()) != 'q')
  28. {
  29. switch (ch)
  30. {
  31. case 'f':
  32. change_font();
  33. break;
  34. case 's':
  35. change_size();
  36. break;
  37. case 'a':
  38. change_alignment();
  39. break;
  40. case 'b':
  41. case 'i':
  42. case 'u':
  43. change_toggle(ch);
  44. break;
  45. default: fputs("Wrong!", stderr);
  46. break;
  47. }
  48. putchar('\n');
  49. }
  50. printf("Bye!\n");
  51. return 0;
  52. }
  53. void eatline(void)
  54. {
  55. while (getchar() != '\n')
  56. continue;
  57. }
  58. int get_first(void)
  59. {
  60. int ch;
  61. do
  62. {
  63. ch = getchar();
  64. } while (isspace(ch));
  65. eatline();
  66. return ch;
  67. }
  68. int get_choice(void)
  69. {
  70. int ch;
  71. printf("ID SIZE ALIGNMENT B I U\n");
  72. printf("%-7u%-9u%-12s", ft.id, ft.sz, alignment[ft.at]);
  73. printf("%-8s%-8s%-8s\n", state[ft.b], state[ft.i], state[ft.u]);
  74. printf("f) change font s) change size a) change alignment\n");
  75. printf("b) toggle bold i) toggle italic u) toggle underline\n");
  76. printf("q) quit\n");
  77. while (ch = get_first(), NULL == strchr("fsabiuq", ch))
  78. printf("Please enter with f, s, a, b, i, u or q: ");
  79. return ch;
  80. }
  81. void change_font(void)
  82. {
  83. int ch;
  84. uint id;
  85. printf("Enter font id (0-255): ");
  86. while (scanf("%u", &id) != 1)
  87. {
  88. while ((ch = getchar()) != '\n')
  89. putchar(ch);
  90. printf(" is not a id.\n");
  91. printf("Please enter a number such as 0, 5 or 255: ");
  92. }
  93. ft.id = id & 0XFF; // 确保不超过 255
  94. }
  95. void change_size(void)
  96. {
  97. int ch;
  98. uint sz;
  99. printf("Enter font sz (0-127): ");
  100. while (scanf("%u", &sz) != 1)
  101. {
  102. while ((ch = getchar()) != '\n')
  103. putchar(ch);
  104. printf(" is not a size.\n");
  105. printf("Please enter a number such as 0, 5 or 127: ");
  106. }
  107. ft.sz = sz & 0x7F;
  108. }
  109. void change_alignment(void)
  110. {
  111. int ch;
  112. printf("Select alignment:\n");
  113. printf("l) left c) center r) right\n");
  114. while (ch = get_first(), NULL == strchr("lcr", ch))
  115. printf("Please enter with l, c or r: ");
  116. ft.at = (ch == 'l' ? 0 : ch == 'c' ? 1 : 2); // 理解一下
  117. }
  118. void change_toggle(int ch)
  119. {
  120. if (ch == 'b')
  121. ft.b ^= 1;
  122. else if (ch == 'i')
  123. ft.i ^= 1;
  124. else
  125. ft.u ^= 1;
  126. }

输出结果(经测试暂时无误):

题目7

方法:用指定位代表相关状态,并操作相关位,一般是先清空相关位为零(&运算),然后放入目标位(|运算)。示例代码15_7.c:

  1. #include <stdio.h>
  2. #include <ctype.h> // 提供 isspace() 函数
  3. #include <string.h> // 提供 strchr() 函数
  4. typedef unsigned long ulong;
  5. static ulong ft = 0x00001180; //题目初始; 0000 0000 0000 |0000 0001 |0001 100| 00| 0 | 0 | 0
  6. //从右往左数, 第1位表示U, 第2位表示I, 第3位表示B, 第4至5位表示ALIGNMENT, 第6至第12位表示SIZE, 第13至20位表示ID
  7. const char * state[4] = {"off", "on"};
  8. const char * alignment[7] = {"left", "center", "right"};
  9. void eatline(void);
  10. int get_first(void);
  11. int get_choice(void);
  12. void change_font(void);
  13. void change_size(void);
  14. void change_alignment(void);
  15. void change_toggle(int ch);
  16. int main(void)
  17. {
  18. int ch;
  19. while ((ch = get_choice()) != 'q')
  20. {
  21. switch (ch)
  22. {
  23. case 'f':
  24. change_font();
  25. break;
  26. case 's':
  27. change_size();
  28. break;
  29. case 'a':
  30. change_alignment();
  31. break;
  32. case 'b':
  33. case 'i':
  34. case 'u':
  35. change_toggle(ch);
  36. break;
  37. default: fputs("Error!", stderr);
  38. }
  39. putchar('\n');
  40. }
  41. printf("Bye!\n");
  42. return 0;
  43. }
  44. void eatline(void)
  45. {
  46. while (getchar() != '\n')
  47. continue;
  48. }
  49. int get_first(void)
  50. {
  51. int ch;
  52. do
  53. {
  54. ch = getchar();
  55. } while (isspace(ch));
  56. eatline();
  57. return ch;
  58. }
  59. int get_choice(void)
  60. {
  61. int ch;
  62. printf("ID SIZE ALIGNMENT B I U\n");
  63. printf("%-7lu%-9lu%-12s", (ft >> 12) & 0XFF, (ft >> 5) & 0x7F, alignment[(ft >> 3) & 0x03]);
  64. printf("%-8s%-8s%-8s\n", state[(ft >> 2) & 1], state[(ft >> 1) & 1], state[ft & 1]);
  65. printf("f) change font s) change size a) change alignment\n");
  66. printf("b) toggle bold i) toggle italic u) toggle underline\n");
  67. printf("q) quit\n");
  68. while (ch = get_first(), NULL == strchr("fsabiuq", ch))
  69. printf("Please enter with f, s, a, b, i, u or q: ");
  70. return ch;
  71. }
  72. void change_font(void)
  73. {
  74. int ch;
  75. ulong id;
  76. printf("Enter font id (0-255): ");
  77. while (scanf("%lu", &id) != 1)
  78. {
  79. while ((ch = getchar()) != '\n')
  80. putchar(ch);
  81. printf(" is not a id.\n");
  82. printf("Please enter a number such as 0, 5 or 255: ");
  83. }
  84. id &= 0XFF, id <<= 12;
  85. for (int i = 12; i < 20; ++i)
  86. ft &= ~(ulong)(1 << i); //将指定位 置为零
  87. ft |= id; //填入目标位
  88. }
  89. void change_size(void)
  90. {
  91. int ch;
  92. ulong sz;
  93. printf("Enter font sz (0-127): ");
  94. while (scanf("%lu", &sz) != 1)
  95. {
  96. while ((ch = getchar()) != '\n')
  97. putchar(ch);
  98. printf(" is not a size.\n");
  99. printf("Please enter a number such as 0, 5 or 127: ");
  100. }
  101. sz &= 0X7F, sz <<= 5;
  102. for (int i = 5; i < 12; ++i)
  103. ft &= ~(ulong)(1 << i);
  104. ft |= sz;
  105. }
  106. void change_alignment(void)
  107. {
  108. int ch;
  109. printf("Select alignment:\n");
  110. printf("l) left c) center r) right\n");
  111. while (ch = get_first(), NULL == strchr("lcr", ch))
  112. printf("Please enter with l, c or r: ");
  113. ft &= ~(ulong)(1 << 3), ft &= ~(ulong)(1 << 4);
  114. ft = ft | (ch == 'c' ? (ulong)(1 << 3) : ch == 'r' ? (ulong)(1 << 4) : 0);
  115. }
  116. void change_toggle(int ch)
  117. {
  118. if (ch == 'b')
  119. {
  120. if (ft & 0x04)
  121. ft &= ~(ulong)(0x04);
  122. else
  123. ft |= (ulong)(0x04);
  124. }
  125. else if (ch == 'i')
  126. {
  127. if (ft & 0x02)
  128. ft &= ~(ulong)(0x02);
  129. else
  130. ft |= (ulong)(0x02);
  131. }
  132. else
  133. {
  134. if (ft & 0x01)
  135. ft &= ~(ulong)(0x01);
  136. else
  137. ft |= (ulong)(0x01);
  138. }
  139. }

输出结果:

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/空白诗007/article/detail/955304
推荐阅读
相关标签
  

闽ICP备14008679号