赞
踩
按位取反运算符:~,作用:将对应二进制码取反。代码示例example.c:
- #include <stdio.h>
-
- int main(void)
- {
- unsigned char val = 2; // 00000010
- unsigned char new_val = ~val; // 11111101
-
- printf("Now val is %d\n", val);
- printf("Now new_val is %d\n", new_val);
-
- return 0;
- }
'运行
输出结果:
按位与运算符:&,作用:两个二进制位都为真时取真。代码示例example.c :
- #include <stdio.h>
-
- int main(void)
- {
- unsigned char var1 = 0x93; // 147 10010011
- unsigned char var2 = 0x3d; // 61 00111101
-
- unsigned char var3 = var1 & var2; //0x11 17 00010001
- printf("var1 is %d\n", var1);
- printf("var2 is %d\n", var2);
- printf("var3 is %d\n", var3);
-
- var1 &= var2; //Equal to var1 = var1 & var2;
- printf("Now var1 is %d\n", var1);
-
- return 0;
- }
'运行
输出结果:
按位或运算符:|,作用:当两个二进制位有一个为真时取真。代码示例example.c:
- #include <stdio.h>
-
- int main(void)
- {
- unsigned char var1 = 0x93; // 10010011 147
- unsigned char var2 = 0x3d; // 00111101 61
- unsigned char var3 = var1 | var2; // 10111111 0xbf 191
-
- printf("var1 = %d\n", var1);
- printf("var2 = %d\n", var2);
- printf("var3 = %d\n", var3);
-
- var1 |= var2; // Equal to var1 = var1 | var2
- printf("Now var1 = %d\n", var1);
-
- return 0;
- }
输出结果:
按位异或运算符:^,作用:当且仅当两个二进制位中仅有一个为真时取真。代码示例example.c:
- #include <stdio.h>
-
- int main(void)
- {
- unsigned char var1 = 0x93; // 10010011 147
- unsigned char var2 = 0x3d; // 00111101 61
- unsigned char var3 = var1 ^ var2; // 10101110 0xae 174
-
- printf("var1 = %d\n", var1);
- printf("var2 = %d\n", var2);
- printf("var3 = %d\n", var3);
-
- var1 ^= var2; // Equal to var1 = var1 ^ var2;
- printf("Now var1 = %d\n", var1);
-
- return 0;
- }
输出结果:
左移运算符:<<,作用:将其左侧运算对象每一位的值向左移动其右侧运算对象指定的位数,左侧运算对象移除左末端位的值丢失,用0填充空出的位置。示例代码:example.c
- #include <stdio.h>
-
- int main(void)
- {
- int stonk = 1; // 00000001
- int onkoo;
-
- onkoo = stonk << 2; // 00000100
- stonk <<= 2;
- printf("onkoo = %d\n", onkoo);
- printf("stonk = %d\n", stonk);
-
- return 0;
- }
'运行
输出结果:
右移运算符:>>,作用:将其左侧运算对象每一位的值向右移动其右侧运算对象指定的位数,左侧运算对象移除右末端位的值丢失,对于有符号类型,取决于机器用0或者1填充空出的位置,对于无符号类型,都用0填充空出的位置。示例代码example.c:
- #include <stdio.h>
-
- int main(void)
- {
- signed char var1 = 0x8a; // 10001010 -(256-138) = -118
- signed char var2 = var1 >> 2; // 11100010 -(256 - 0xe2) = -(256-226) = -30
- unsigned char var3 = 0x8a >> 2; // 00100010 0x22 34
-
- printf("var1 = %d\n", var1);
- printf("var2 = %d\n", var2);
- printf("var3 = %d\n", var3);
-
- return 0;
- }
输出结果:
程序清单15.1,binbit.c:
- /*binbit.c -- 使用位操作显示二进制 */
- #include <stdio.h>
- #include <limits.h> //提供 CHAR_BIT 的定义,CHAR_BIT 表示每字节的位数
-
- char * itobs(int, char *);
- void show_bstr(const char *);
-
- int main(void)
- {
- char bin_str[CHAR_BIT * sizeof(int) + 1];
- int number;
-
- puts("Enter integers and see them in binary.");
- puts("Non-numeric input terminates program.");
- while (scanf("%d", &number) == 1)
- {
- itobs(number, bin_str);
- printf("%d is ", number);
- show_bstr(bin_str);
- putchar('\n');
- }
- puts("Bye!");
-
- return 0;
- }
-
- char * itobs(int n, char * ps)
- {
- int i;
- static const int size = CHAR_BIT * sizeof(int);
-
- for (i = size - 1; i >= 0; i--, n >>=1) // 7 -> 0000 0111
- ps[i] = (01 & n) + '0'; // 0000 0001
- ps[size] = '\0';
-
- return ps;
- }
-
- void show_bstr(const char * str)
- {
- int i = 0;
-
- while(str[i])
- {
- putchar(str[i]);
- if (++i % 4 == 0 && str[i])
- putchar(' ');
- }
- }
输出结果:
程序清单15.2, invert4.c:
- /*invert4.c -- 使用位操作显示二进制 */
- #include <stdio.h>
- #include <limits.h> //提供 CHAR_BIT 的定义,CHAR_BIT 表示每字节的位数
-
- char * itobs(int, char *);
- void show_bstr(const char *);
- int invert_end(int num, int bits);
-
- int main(void)
- {
- char bin_str[CHAR_BIT * sizeof(int) + 1];
- int number;
-
- puts("Enter integers and see them in binary.");
- puts("Non-numeric input terminates program.");
- while (scanf("%d", &number) == 1)
- {
- itobs(number, bin_str);
- printf("%d is ", number);
- show_bstr(bin_str);
- putchar('\n');
- number = invert_end(number, 4);
- printf("Inverting the last 4 bits gives\n");
- show_bstr(itobs(number, bin_str));
- putchar('\n');
- }
- puts("Bye!");
-
- return 0;
- }
-
- char * itobs(int n, char * ps)
- {
- int i;
- static const int size = CHAR_BIT * sizeof(int);
-
- for (i = size - 1; i >= 0; i--, n >>= 1) // 7 -> 0000 0111
- ps[i] = (01 & n) + '0'; // 0000 0001
- ps[size] = '\0';
-
- return ps;
- }
-
- void show_bstr(const char * str)
- {
- int i = 0;
-
- while(str[i])
- {
- putchar(str[i]);
- if (++i % 4 == 0 && str[i])
- putchar(' ');
- }
- }
-
- int invert_end(int num, int bits)
- {
- int mask = 0;
- int bitval = 1;
-
- while (bits-- > 0)
- {
- mask |= bitval;
- bitval <<= 1;
- }
-
- return num ^ mask;
- }
'运行
输出结果:
程序清单15.3,fields.c:
- /* fields.c -- 定义并使用字段 */
- #include <stdio.h>
- #include <stdbool.h>
-
- /* 线的样式 */
- #define SOLID 0
- #define DOTTED 1
- #define DASHED 2
- /* 三原色 */
- #define BLUE 4
- #define GREEN 2
- #define RED 1
- /* 混合色 */
- #define BLACK 0
- #define YELLOW (RED | GREEN)
- #define MAGENTA (RED | BLUE)
- #define CYAN (GREEN | BLUE)
- #define WHITE (RED | GREEN | BLUE)
-
- const char * colors[8] = { "black", "red", "green", "yellow",
- "blue", "magenta", "cyan", "white" };
-
- struct box_props {
- bool opaque : 1;
- unsigned int fill_color : 3;
- unsigned int : 4;
- bool show_border : 1;
- unsigned int border_color : 3;
- unsigned int border_style : 2;
- unsigned int : 2;
- };
-
- void show_settings(const struct box_props * pb);
-
- int main(void)
- {
- /* 创建并使用 box_props 结构 */
- struct box_props box = { true, YELLOW, true, GREEN, DASHED };
-
- printf("Original box settings:\n");
- show_settings(&box);
-
- box.opaque = false;
- box.fill_color = WHITE;
- box.border_color = MAGENTA;
- box.border_style = SOLID;
- printf("\nModified box settings:\n");
- show_settings(&box);
-
- return 0;
- }
-
- void show_settings(const struct box_props * pb)
- {
- printf("Box is %s.\n", pb->opaque == true ? "opaque" : "transparent");
- printf("The fill color is %s.\n", colors[pb->fill_color]);
- printf("Border %s.\n", pb->show_border == true ? "shown" : " not shown");
- printf("The border color is %s.\n", colors[pb->border_color]);
- printf("The border style is ");
- switch (pb->border_style)
- {
- case SOLID: printf("solid.\n"); break;
- case DOTTED: printf("dotted.\n"); break;
- case DASHED: printf("dashed.\n"); break;
- default: printf("unknown type.\n");
- }
- }
'运行
输出结果:
程序清单15.4, dualview.c:
- /* dualview.c -- 位字段和按位运算符 */
- #include <stdio.h>
- #include <stdbool.h>
- #include <limits.h>
- /* 位字段符号常量 */
- /* 边框线样式 */
- #define SOLID 0
- #define DOTTED 1
- #define DASHED 2
- /* 三原色 */
- #define BLUE 4
- #define GREEN 2
- #define RED 1
- /* 混合色 */
- #define BLACK 0
- #define YELLOW (RED | GREEN)
- #define MAGENTA (RED | BLUE)
- #define CYAN (GREEN | BLUE)
- #define WHITE (RED | GREEN | BLUE)
-
- /* 按位方法用到的符号常量 */
- #define OPAQUE 0x1
- #define FILL_BLUE 0x8
- #define FILL_GREEN 0x4
- #define FILL_RED 0x2
- #define FILL_MASK 0xE
- #define BORDER 0x100
- #define BORDER_BLUE 0x800
- #define BORDER_GREEN 0x400
- #define BORDER_RED 0x200
- #define BORDER_MASK 0xE00
- #define B_SOLID 0
- #define B_DOTTED 0x1000
- #define B_DASHED 0x2000
- #define STYLE_MASK 0x3000
-
- const char * colors[8] = { "black", "red", "green", "yellow", "blue", "magenta",
- "cyan", "white" };
-
- struct box_props {
- bool opaque : 1;
- unsigned int fill_color : 3;
- unsigned int : 4;
- bool show_border : 1;
- unsigned int border_color : 3;
- unsigned int border_style : 2;
- unsigned int : 2;
- };
-
- union Views /* 把数据看作结构或 unsigned short 类型的变量 */
- {
- struct box_props st_view;
- unsigned short us_view;
- };
-
- void show_settings(const struct box_props * pb);
- void show_settings1(unsigned short);
- char * itobs(int n, char * ps);
-
- int main(void)
- {
- /* 创建 Views 联合,并初始化initialize struct box view */
- union Views box = { { true, YELLOW, true, GREEN, DASHED } };
- char bin_str[8 * sizeof(unsigned int) + 1];
-
- printf("Original box settings:\n");
- show_settings(&box.st_view);
- printf("\nBox settings using unsigned int view:\n");
- show_settings1(box.us_view);
- printf("bits are %s\n", itobs(box.us_view, bin_str));
- box.us_view &= ~FILL_MASK; /* 把表示填充色的位清0 */
- box.us_view |= (FILL_BLUE | FILL_GREEN); /* 重置填充色 */
- box.us_view ^= OPAQUE; /* 切换是否透明的位 */
- box.us_view |= BORDER_RED; /* 错误的方法 */
- box.us_view &= ~STYLE_MASK;/* 把样式的位清0 */
- box.us_view |= B_DOTTED; /* 把样式设置为点 */
- printf("\nModified box settings:\n");
- show_settings(&box.st_view);
- printf("\nBox settings using unsigned int view:\n");
- show_settings1(box.us_view);
- printf("bits are %s\n", itobs(box.us_view, bin_str));
-
- return 0;
- }
-
- void show_settings(const struct box_props * pb)
- {
- printf("Box is %s.\n", pb->opaque == true ? "opaque" : "transparent");
- printf("The fill color is %s.\n", colors[pb->fill_color]);
- printf("Border %s.\n", pb->show_border == true ? "shown" : " not shown");
- printf("The border color is %s.\n", colors[pb->border_color]);
- printf("The border style is ");
- switch (pb->border_style)
- {
- case SOLID : printf("solid.\n"); break;
- case DOTTED: printf("dotted.\n"); break;
- case DASHED: printf("dashed.\n"); break;
- default : printf("unknown type.\n");
- }
- }
-
- void show_settings1(unsigned short us)
- {
- printf("box is %s.\n", (us & OPAQUE) == OPAQUE ? "opaque" : "transparent");
- printf("The fill color is %s.\n", colors[(us >> 1) & 07]);
- printf("Border %s.\n", (us & BORDER) == BORDER ? "shown" : "not shown");
- printf("The border style is ");
- switch (us & STYLE_MASK)
- {
- case B_SOLID : printf("solid.\n"); break;
- case B_DOTTED : printf("dotted.\n"); break;
- case B_DASHED : printf("dashed.\n"); break;
- default : printf("unknow type.\n");
- }
- printf("The border color is %s.\n", colors[(us >> 9) & 07]);
- }
-
- char * itobs(int n, char * ps)
- {
- int i;
- static const int size = CHAR_BIT * sizeof(int);
-
- for (i = size - 1; i >= 0; i--, n >>=1) // 7 -> 0000 0111
- ps[i] = (01 & n) + '0'; // 0000 0001
- ps[size] = '\0';
-
- return ps;
- }
输出结果:
程序清单15.5,align.c:
- /* align.c -- 使用 _Alignof 和 _Alignas (C!!) */
- #include <stdio.h>
-
- int main(void)
- {
- double dx;
- char ca;
- char cx;
- double dz;
- char cb;
- char _Alignas(double) cz;
-
- printf("char alignment: %zd\n", _Alignof(char));
- printf("double alignment: %zd\n", _Alignof(double));
- printf("&dx: %p\n", &dx);
- printf("&ca: %p\n", &ca);
- printf("&cx: %p\n", &cx);
- printf("&dz: %p\n", &dz);
- printf("&cb: %p\n", &cb);
- printf("&cz: %p\n", &cz);
-
- return 0;
- }
输出结果:
编程练习:
题目1
方法一:使用位操作。代码示例15_1_1.c:
- #include <stdio.h>
- #include <ctype.h> // 提供 isspace() 函数
- #include <string.h> // 提供 strchr() 函数
- #define SIZE 50
-
- int get_bstr(char * st, int n);
- char * del_space(char * st);
- int btoi(char * st);
-
- int main(void)
- {
- char binstr[SIZE];
- int number;
-
- printf("Please input a binary string, [Enter] to quit: ");
- while(get_bstr(binstr, SIZE))
- {
- number = btoi(del_space(binstr));
- printf("Binary string %s is %d in decimal.\n", binstr, number);
- printf("Please input another binary string, [Enter] to quit: ");
- }
-
- return 0;
- }
-
- int get_bstr(char * st, int n) //通过指针获取字符串并返回字符串的长度
- {
- char ch;
- int i;
-
- //获取仅含 0或1 的字符串 ,注意通过 getchar() 获取的是字符而不是数字,加单引号
- for (i = 0; i < n - 1 && (ch = getchar()) != '\n' && (ch == '1' || ch == '0'
- || isspace(ch)); i++)
- st[i] = ch;
- st[i] = '\0'; //最后一个字符设为空字符
- //处理超出 n的大小的字符
- if (ch != '\n')
- while (getchar() != '\n')
- continue;
-
- return i;
- }
-
- char * del_space(char * st) // 删去字符中的空格(指针改变了字符串 st)
- {
- int i;
- char * find = NULL;
-
- while ((find = strchr(st, ' ')))
- {
- for (i = 0; find[i]; i++) // find[i] Equal to *(find + i)
- find[i] = find[i + 1];
- }
-
- return st;
- }
-
- int btoi(char * st) // 通过按位或运算符生成一个目标数
- {
- int num = 0;
- int i;
-
- for (i = 0; st[i]; i++)
- {
- num <<= 1; // Equal to num = num << 1
- num |= (st[i] - '0'); // Equal to num = num | (st[i] - '0')
- }
-
- return num;
- }
输出结果:
方法二:直接计算,两种方法。代码示例15_1_2.c:
- #include <stdio.h>
- #include <string.h> // 提供 strlen() 函数
- #define SIZE 50
-
- int btoi(char * st);
- int btoi1(char * st);
-
- int main(void)
- {
- char str[SIZE];
-
- printf("Please input a binary string: ");
- gets(str);
- printf("Binary string %s is %d in decimal.\n", str, btoi(str));
- printf("Binary string %s is %d in deciaml.\n", str, btoi1(str));
-
- return 0;
- }
-
- int btoi(char * st)
- {
- int sum = 0;
-
- while (*st) // 读取字符时从左往右读取,每多读取一个数就增大两倍
- {
- sum *= 2;
- sum += *st - '0';
- st++;
- }
-
- return sum;
- }
-
- int btoi1(char * st) // 从左往右理解二进制字符串,直观理解
- {
- int sum = 0;
- int len = strlen(st);
- int i, exp;
-
- for (i = len - 1, exp = 1; i >= 0; i--, exp *= 2)
- sum += exp * (st[i] - '0');
-
- return sum;
- }
输出结果:
题目2
方法一:先转换为数字,运算完成后再转换为字符,递归实现。代码示例15_2_1.c:
- #include <stdio.h>
- #include <ctype.h> // 提供 isspace() 函数
- #include <string.h> // 提供 strchr() 函数
- #include <stdlib.h> // 提供 EXIT_FAILURE
- #define SIZE 50
-
- int btoi(char * st);
- void print_bstr(unsigned int n);
-
- int main(int argc, char * argv[])
- {
- int num1, num2;
-
- if (argc != 3)
- {
- fprintf(stderr, "Usage: %s, binary_str1, binary_str2\n", *argv);
- exit(EXIT_FAILURE);
- }
- num1 = btoi(argv[1]);
- num2 = btoi(argv[2]);
- printf("num1 = %d\n", num1);
- printf("~num1 = %d\n", ~num1);
-
- printf("~%s is ", argv[1]);
- print_bstr(~num1);
- putchar('\n');
- printf("~%s is ", argv[2]);
- print_bstr(~num2);
- putchar('\n');
-
- printf("%s & %s is ", argv[1], argv[2]);
- print_bstr(num1 & num2);
- putchar('\n');
-
- printf("%s | %s is ", argv[1], argv[2]);
- print_bstr(num1 | num2);
- putchar('\n');
-
- printf("%s ^ %s is ", argv[1], argv[2]);
- print_bstr(num1 ^ num2);
- putchar('\n');
-
- return 0;
- }
-
- int btoi(char * st) // 通过按位或运算符生成一个目标数
- {
- int num = 0;
- int i;
-
- for (i = 0; st[i]; i++)
- {
- num <<= 1; // Equal to num = num << 1
- num |= (st[i] - '0'); // Equal to num = num | (st[i] - '0')
- }
-
- return num;
- }
-
- void print_bstr(unsigned int n) // 以二进制字符格式输出一个数的二进制格式
- {
- static long loop = 0; // 函数执行期间该值不变
-
- if (!loop && !n)
- {
- putchar('0');
- return;
- }
- if (n)
- {
- loop++;
- print_bstr(n / 2);
- }
- else
- return;
- putchar('0' + (n % 2));
- if ((--loop % 4) == 0)
- putchar(' ');
- }
输出结果:
方法二:先转换为数字,运算完成后再转换为字符,位操作实现。代码示例15_2_1.c:
- #include <stdio.h>
- #include <stdlib.h> // 提供 EXIT_FAILURE
-
- int bstr_to_dec(const char * str); // 2 进制字符串转换为 10 进制
- char *itobs(int n, char *str); // 将一个数转换为 2 进制字符串
-
- int main(int argc, char *argv[])
- {
- char bstr[8 * sizeof(int) + 1];
-
- if (argc != 3)
- {
- fprintf(stderr, "Usage: %s binarynum1 binarynum2\n", argv[0]);
- exit(EXIT_FAILURE);
- }
- int v1 = bstr_to_dec(argv[1]);
- int v2 = bstr_to_dec(argv[2]);
- printf("~%s = %s\n", argv[1], itobs(~v1, bstr));
- printf("~%s = %s\n", argv[2], itobs(~v2, bstr));
- printf("%s & %s = %s\n", argv[1], argv[2], itobs(v1 & v2, bstr));
- printf("%s | %s = %s\n", argv[1], argv[2], itobs(v1 | v2, bstr));
- printf("%s ^ %s = %s\n", argv[1], argv[2], itobs(v1 ^ v2, bstr));
-
- return 0;
- }
-
- int bstr_to_dec(const char * str)
- {
- int val = 0;
-
- while (*str)
- val = val * 2 + ((*str++) - '0');
-
- return val;
- }
-
- char *itobs(int n, char *str)
- {
- int sz = 8 * sizeof(int);
-
- for (int i = sz - 1; i >= 0; --i, n >>= 1)
- str[i] = (n & 1) + '0';
- str[sz] = '\0';
-
- return str;
- }
输出结果:
方法三:按位直接计算,但该方法不适用于计算取反~。示例代码15_2_3.c:
- #include <stdio.h>
- #include <stdlib.h> //提供 EXIT_FAILURE
-
- void funca(char *a, char *b); // &运算
- void funcb(char *a, char *b); // ^运算
- void funcc(char *a, char *b); // |运算
-
- int main(int argc, char **argv)
- {
- char ch;
-
- if(argc != 4)
- {
- fprintf(stderr, "Usage:%s [string] [string] [char]\n", argv[0]);
- exit(EXIT_FAILURE);
- }
- 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;
- default: fprintf(stderr, "Wrong!\n");
- break;
- }
-
- return 0;
- }
-
- void funca(char *a, char *b)
- {
- while(*a && *b)
- {
- int x = ((*a) - '0') & ((*b) - '0');
- putchar(x + '0');
- a++;
- b++;
- }
- putchar('\n');
- }
-
- void funcb(char *a, char *b)
- {
- while(*a && *b)
- {
- int x = ((*a) - '0') ^ ((*b) - '0');
- putchar(x + '0');
- a++;
- b++;
- }
- putchar('\n');
- }
-
- void funcc(char *a, char *b)
- {
- while(*a && *b)
- {
- int x = ((*a) - '0') | ((*b) - '0');
- putchar(x + '0');
- a++;
- b++;
- }
- putchar('\n');
- }
输出结果:
题目3
方法一:直接按位&运算。示例代码15_3_1.c:
- #include <stdio.h>
-
- int count_openbit(unsigned int n);
-
- int main(void)
- {
- int num;
-
- printf("Please input an integer(q to quit): ");
- while (scanf("%d", &num))
- {
- while (getchar() != '\n')
- continue;
- printf("Here are %d bits opend in %d.\n", count_openbit(num), num);
- printf("Please input an integer(q to quit): ");
- }
-
- return 0;
- }
-
- int count_openbit(unsigned int n)
- {
- int count = 0;
-
- while (n)
- {
- count += (n & 1);
- n >>= 1;
- }
-
- return count;
- }
输出结果:
方法二:显示详细信息。示例代码15_3_2.c:
- #include <stdio.h>
- #define TEST_NUM 9
-
- char * itobs(int n, char *str);
- int onbits(int x);
-
- int main(void)
- {
- int x = TEST_NUM;
- char bstr[8 * sizeof(int) + 1];
-
- printf("%d(%s) has %d bit on.\n", x, itobs(x, bstr), onbits(x));
-
- return 0;
- }
-
- char *itobs(int n, char *str)
- {
- int sz = 8 * sizeof(int);
-
- for (int i = sz - 1; i >= 0; --i, n >>= 1)
- {
- str[i] = (n & 1) + '0';
- }
- str[sz] = '\0';
-
- return str;
- }
-
- int onbits(int x)
- {
- int sum = 0;
-
- for (int i = 8 * sizeof(int) - 1; i >= 0; --i)
- {
- sum += (x >> i) & 1;
- }
-
- return sum;
- }
输出结果:
题目4
方法:移动数的位进行按位与运算,两个函数实现相同的功能。示例代码15_4.c:
- #include <stdio.h>
- #include <stdbool.h>
- #include <stdlib.h>
- #define TEST_VALUE 9 // 1001
-
- bool isbit_open(int num, int pos);
- bool isbit_open1(int num, int pos);
-
- int main(void)
- {
- int size = 8 * sizeof(int);
- int i;
-
- for (i = 0; i < size; i++)
- printf("The %dth of %d is %s.\n", i + 1,
- TEST_VALUE, isbit_open(TEST_VALUE, i + 1) ? "opend" : "closed");
-
- return 0;
- }
-
- bool isbit_open(int num, int pos)
- {
- if (pos <= 0)
- {
- fputs("The position can't be 0.", stderr);
- exit(1);
- }
-
- return (num & (1 << (pos - 1)));
- }
-
- bool isbit_open1(int num, int pos)
- {
- if (pos <= 0)
- {
- fputs("The position can't be 0.", stderr);
- exit(1);
- }
-
- return (num >> (pos - 1)) & 1;
- }
函数1或2输出结果:
题目5
方法:循环移动或者直接移动位,两种函数实现功能相同,示例代码15_5.c:
- #include <stdio.h>
- #include <limits.h> //Support for CHAR_BIT
- #define TEST_VALUE 9
-
- char * itobs(int n, char *str);
- unsigned int rotate_l(unsigned int num, int bits); // 将数的二进制位向左循环移动指定位
- unsigned int rotate_l_2(unsigned int num, int bits);
-
- int main(void)
- {
- char bstr[CHAR_BIT * sizeof(unsigned int) + 1];
-
- printf("%d in binary is \n%s.\n", TEST_VALUE, itobs(TEST_VALUE, bstr));
- printf("After rotate to the left for 4 bits, the number in binary is \n%s.\n",
- itobs(rotate_l(TEST_VALUE, 4), bstr));
- printf("After rotate to the left for 4 bits, the number in binary is \n%s.\n",
- itobs(rotate_l_2(TEST_VALUE, 4), bstr));
-
- return 0;
-
- }
-
- char *itobs(int n, char *str)
- {
- int sz = CHAR_BIT * sizeof(int);
-
- for (int i = sz - 1; i >= 0; --i, n >>= 1)
- str[i] = (n & 1) + '0';
- str[sz] = '\0';
-
- return str;
- }
-
- unsigned int rotate_l(unsigned int num, int bits)
- {
- int i;
-
- for (i = 0; i < bits; i++) // 先保存最左侧的一位,再将数向右移动1位并或运算,如此循环
- num = (num >> (CHAR_BIT * sizeof(unsigned int) - 1)) | (num << 1);
-
- return num;
- }
-
- unsigned int rotate_l_2(unsigned int num, int bits)
- {
- static const int size = CHAR_BIT * sizeof(unsigned int);
-
- bits %= size;
-
- return (num << bits) | (num >> (size - bits));
- }
'运行
输出结果:
题目6
方法:直接更改结构体中的内容即可。示例代码15_6.c:
- #include <stdio.h>
- #include <ctype.h> // 提供 isspace() 函数
- #include <string.h> // 提供 strchr() 函数
-
- typedef unsigned int uint;
- typedef struct
- {
- uint id : 8;
- uint sz : 7;
- uint at : 2;
- uint b : 1;
- uint i : 1;
- uint u : 1;
- } font;
-
- static font ft = { 1, 12, 0, 0, 0, 0 };
- const char * state[4] = { "off", "on" };
- const char * alignment[7] = { "left", "center", "right" };
-
- void eatline(void);
- int get_first(void);
- int get_choice(void);
- void change_font(void);
- void change_size(void);
- void change_alignment(void);
- void change_toggle(int ch);
-
- int main(void)
- {
- int ch;
-
- while ((ch = get_choice()) != 'q')
- {
- switch (ch)
- {
- case 'f':
- change_font();
- break;
- case 's':
- change_size();
- break;
- case 'a':
- change_alignment();
- break;
- case 'b':
- case 'i':
- case 'u':
- change_toggle(ch);
- break;
- default: fputs("Wrong!", stderr);
- break;
- }
- putchar('\n');
- }
- printf("Bye!\n");
-
- return 0;
- }
-
- void eatline(void)
- {
- while (getchar() != '\n')
- continue;
- }
-
- int get_first(void)
- {
- int ch;
-
- do
- {
- ch = getchar();
- } while (isspace(ch));
- eatline();
-
- return ch;
- }
-
- int get_choice(void)
- {
- int ch;
-
- printf("ID SIZE ALIGNMENT B I U\n");
- printf("%-7u%-9u%-12s", ft.id, ft.sz, alignment[ft.at]);
- printf("%-8s%-8s%-8s\n", state[ft.b], state[ft.i], state[ft.u]);
- printf("f) change font s) change size a) change alignment\n");
- printf("b) toggle bold i) toggle italic u) toggle underline\n");
- printf("q) quit\n");
-
- while (ch = get_first(), NULL == strchr("fsabiuq", ch))
- printf("Please enter with f, s, a, b, i, u or q: ");
-
- return ch;
- }
-
- void change_font(void)
- {
- int ch;
- uint id;
-
- printf("Enter font id (0-255): ");
- while (scanf("%u", &id) != 1)
- {
- while ((ch = getchar()) != '\n')
- putchar(ch);
- printf(" is not a id.\n");
- printf("Please enter a number such as 0, 5 or 255: ");
- }
- ft.id = id & 0XFF; // 确保不超过 255
- }
-
- void change_size(void)
- {
- int ch;
- uint sz;
-
- printf("Enter font sz (0-127): ");
- while (scanf("%u", &sz) != 1)
- {
- while ((ch = getchar()) != '\n')
- putchar(ch);
- printf(" is not a size.\n");
- printf("Please enter a number such as 0, 5 or 127: ");
- }
- ft.sz = sz & 0x7F;
- }
-
- void change_alignment(void)
- {
- int ch;
-
- printf("Select alignment:\n");
- printf("l) left c) center r) right\n");
- while (ch = get_first(), NULL == strchr("lcr", ch))
- printf("Please enter with l, c or r: ");
- ft.at = (ch == 'l' ? 0 : ch == 'c' ? 1 : 2); // 理解一下
- }
-
- void change_toggle(int ch)
- {
- if (ch == 'b')
- ft.b ^= 1;
- else if (ch == 'i')
- ft.i ^= 1;
- else
- ft.u ^= 1;
- }
输出结果(经测试暂时无误):
题目7
方法:用指定位代表相关状态,并操作相关位,一般是先清空相关位为零(&运算),然后放入目标位(|运算)。示例代码15_7.c:
- #include <stdio.h>
- #include <ctype.h> // 提供 isspace() 函数
- #include <string.h> // 提供 strchr() 函数
-
- typedef unsigned long ulong;
- static ulong ft = 0x00001180; //题目初始; 0000 0000 0000 |0000 0001 |0001 100| 00| 0 | 0 | 0
- //从右往左数, 第1位表示U, 第2位表示I, 第3位表示B, 第4至5位表示ALIGNMENT, 第6至第12位表示SIZE, 第13至20位表示ID
- const char * state[4] = {"off", "on"};
- const char * alignment[7] = {"left", "center", "right"};
-
- void eatline(void);
- int get_first(void);
- int get_choice(void);
- void change_font(void);
- void change_size(void);
- void change_alignment(void);
- void change_toggle(int ch);
-
- int main(void)
- {
- int ch;
-
- while ((ch = get_choice()) != 'q')
- {
- switch (ch)
- {
- case 'f':
- change_font();
- break;
- case 's':
- change_size();
- break;
- case 'a':
- change_alignment();
- break;
- case 'b':
- case 'i':
- case 'u':
- change_toggle(ch);
- break;
- default: fputs("Error!", stderr);
- }
- putchar('\n');
- }
- printf("Bye!\n");
-
- return 0;
- }
-
- void eatline(void)
- {
- while (getchar() != '\n')
- continue;
- }
-
- int get_first(void)
- {
- int ch;
-
- do
- {
- ch = getchar();
- } while (isspace(ch));
- eatline();
-
- return ch;
- }
-
- int get_choice(void)
- {
- int ch;
-
- printf("ID SIZE ALIGNMENT B I U\n");
- printf("%-7lu%-9lu%-12s", (ft >> 12) & 0XFF, (ft >> 5) & 0x7F, alignment[(ft >> 3) & 0x03]);
- printf("%-8s%-8s%-8s\n", state[(ft >> 2) & 1], state[(ft >> 1) & 1], state[ft & 1]);
- printf("f) change font s) change size a) change alignment\n");
- printf("b) toggle bold i) toggle italic u) toggle underline\n");
- printf("q) quit\n");
-
- while (ch = get_first(), NULL == strchr("fsabiuq", ch))
- printf("Please enter with f, s, a, b, i, u or q: ");
-
- return ch;
- }
-
- void change_font(void)
- {
- int ch;
- ulong id;
-
- printf("Enter font id (0-255): ");
- while (scanf("%lu", &id) != 1)
- {
- while ((ch = getchar()) != '\n')
- putchar(ch);
- printf(" is not a id.\n");
- printf("Please enter a number such as 0, 5 or 255: ");
- }
- id &= 0XFF, id <<= 12;
- for (int i = 12; i < 20; ++i)
- ft &= ~(ulong)(1 << i); //将指定位 置为零
- ft |= id; //填入目标位
- }
-
- void change_size(void)
- {
- int ch;
- ulong sz;
-
- printf("Enter font sz (0-127): ");
- while (scanf("%lu", &sz) != 1)
- {
- while ((ch = getchar()) != '\n')
- putchar(ch);
- printf(" is not a size.\n");
- printf("Please enter a number such as 0, 5 or 127: ");
- }
- sz &= 0X7F, sz <<= 5;
- for (int i = 5; i < 12; ++i)
- ft &= ~(ulong)(1 << i);
- ft |= sz;
- }
-
- void change_alignment(void)
- {
- int ch;
-
- printf("Select alignment:\n");
- printf("l) left c) center r) right\n");
- while (ch = get_first(), NULL == strchr("lcr", ch))
- printf("Please enter with l, c or r: ");
- ft &= ~(ulong)(1 << 3), ft &= ~(ulong)(1 << 4);
- ft = ft | (ch == 'c' ? (ulong)(1 << 3) : ch == 'r' ? (ulong)(1 << 4) : 0);
- }
-
- void change_toggle(int ch)
- {
- if (ch == 'b')
- {
- if (ft & 0x04)
- ft &= ~(ulong)(0x04);
- else
- ft |= (ulong)(0x04);
- }
- else if (ch == 'i')
- {
- if (ft & 0x02)
- ft &= ~(ulong)(0x02);
- else
- ft |= (ulong)(0x02);
- }
- else
- {
- if (ft & 0x01)
- ft &= ~(ulong)(0x01);
- else
- ft |= (ulong)(0x01);
- }
- }
输出结果:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。