17-编程示例
15.3.8 编程示例
在第9章中,我们用递归的方法编写了一个程序,把数字转换为二进制形式(程序清单9.8)。现在,要用移位运算符来解决相同的问题。程序清单15.1中的程序,读取用户从键盘输入的整数,将该整数和一个字符串地址传递给 itobs() 函数( itobs 表示interger to binary string,即整数转换成二进制字符串)。然后,该函数使用移位运算符计算出正确的1和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;
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;
}
/*4位一组显示二进制字符串 */
void show_bstr(const char * str)
{
int i = 0;
while (str[i]) /* 不是一个空字符 */
{
putchar(str[i]);
if (++i % 4 == 0 && str[i])
putchar(' ');
}
}
程序清单15.1使用 limits.h 中的 CHAR_BIT 宏,该宏表示 char 中的位数。 sizeof 运算符返回 char 的大小,所以表达式 CHAE_BIT sizeof(int) 表示 int 类型的位数。 bin_str 数组的元素个数是 CHAE_BIT sizeof(int) + 1 ,留出一个位置给末尾的空字符。
itobs() 函数返回的地址与传入的地址相同,可以把该函数作为 printf() 的参数。在该函数中,首次执行 for 循环时,对 01 & n 求值。 01 是一个八进制形式的掩码,该掩码除 0 号位是 1 之外,其他所有位都为 0 。因此, 01 & n 就是 n 最后一位的值。该值为 0 或 1 。但是对数组而言,需要的是字符 '0' 或字符 '1' 。该值加上 '0' 即可完成这种转换(假设按顺序编码的数字,如ASCII)。其结果存放在数组中倒数第2个元素中(最后一个元素用来存放空字符)。
顺带一提,用 1 & n 或 01 & n 都可以。我们用八进制 1 而不是十进制 1 ,只是为了更接近计算机的表达方式。
然后,循环执行 i-- 和 n >>= 1 。 i-- 移动到数组的前一个元素, n >>= 1 使 n 中的所有位向右移动一个位置。进入下一轮迭代时,循环中处理的是 n 中新的最右端的值。然后,把该值存储在倒数第 3 个元素中,以此类推。 itobs() 函数用这种方式从右往左填充数组。
可以使用 printf() 或 puts() 函数显示最终的字符串,但是程序清单15.1中定义了 show_bstr() 函数,以4位一组打印字符串,方便阅读。
下面的该程序的运行示例:
Enter integers and see them in binary.
Non-numeric input terminates program.
7
7 is 0000 0000 0000 0000 0000 0000 0000 0111
2013
2013 is 0000 0000 0000 0000 0000 0111 1101 1101
-1
-1 is 1111 1111 1111 1111 1111 1111 1111 1111
32123
32123 is 0000 0000 0000 0000 0111 1101 0111 1011
q
Bye!