编程珠玑第三章有真么一道练习题:seven-segmnt devices provide an inexpensive display ofthe ten decimal digits;
The seven segments are usually numbered as
Write a programthat displays a 16-bit positive integer in five seven-segment digits.The outputis an array of five bytes;bit i of byte j is one if and only if the ith segmentof digit j should be on.
题目的大概意思是:seven-segment devices其实就是我们每人都接触过的计算器。所以的数字都是由数字8的某些部分组成的。
第二章图为8的各个边编了序号。每一个数字对一个唯一的边集,在边集中的边显示,不在其中的不显示。例如:1对应的边集就是{3,5}.现在我们来用程序实现这种设备。
现在我们就要用程序来实现这种设备了。程序的目标就:当给定了一个数字,输出其seven-segmnt表示法。
1.首先我们要构造10个数字对应的边集:
数字 | 边集 |
0 | 2,3,4,5,6,0 |
1 | 3,5 |
2 | 2,4,1,5,0 |
3 | 2,4,1,6,0 |
4 | 3,1,4,6 |
5 | 2,3,1,6,0 |
6 | 2,3,1,5,6,0 |
7 | 2,4,6 |
8 | 1,2,3,4,5,6,0 |
9 | 2,3,4,1,6,0 |
好了,我如果拿到了每个数字的边集,那么显示数字全然不费功夫。给个7我就知道要显示的那个8字的第2,4,6条编。
计算机实现
接下来的目的就是怎么用计算机来实现边集。我这里采用了一个7bit的bitmap来表示每个边集。第bitmap中的0th bit代表0th边,1th bit 代表 1th……。
数字 | 边集 | Bitmap 0 1 2 3 4 5 6 (编号) | 十六进制值 |
0 | 2,3,4,5,6,0 | 1 0 1 1 1 1 1 | 0x5f |
1 | 3,5 | 0 0 0 1 0 1 0 | 0xa |
2 | 2,4,1,5,0 | 1 1 1 0 1 1 0 | 0x76 |
3 | 2,4,1,6,0 | 1 1 1 0 1 0 1 | 0x75 |
4 | 3,1,4,6 | 0 1 0 1 1 0 1 | 0x2d |
5 | 2,3,1,6,0 | 1 1 1 1 0 0 1 | 0x79 |
6 | 2,3,1,5,6,0 | 1 1 1 1 0 1 1 | 0x7a |
7 | 2,4,6 | 0 0 1 0 1 0 1 | 0x15 |
8 | 1,2,3,4,5,6,0 | 1 1 1 1 1 1 1 | 0x7f |
9 | 2,3,4,1,6,0 | 0 1 1 1 1 0 1 | 0x3d |
这样用一个数组就可以表示所有数字的边集。
char num_edges[10]={0x5f,0xa,0x76,0x75,0x2d,0x79,0x7a,0x15,0x7f,0x3d}
2.知道了边集的bitmap,我们怎么知道3th是不是要显示呢?
由于采用了bitmap方式,那个边的编号要和bitmap中的bit位进行匹配。所以我们还需要一个数组来表示边的编码:
边的编号 | Bitmap中边的编号 | 十六进制值 |
0 | 1000000 | 0x40 |
1 | 0100000 | 0x20 |
2 | 0010000 | 0x10 |
3 | 0001000 | 0x8 |
4 | 0000100 | 0x4 |
5 | 0000010 | 0x2 |
6 | 0000001 | 0x1 |
char edge_pos[7]={0x40,0x20,0x10,0x8,0x4,0x2,0x1}
知道了边集的bitmap和边的bitmap编号,拿两者做&运算,结果为true时,则我们就知道要显示那条边。例如:数字4:num_edges[4]& edge_pos[1]运算结果为0100000,结果为true,显示第1th边。而num_edges[4]& edge_pos[0]结果是0,0th是不显示的。
3.接下还有很让我头痛的问题。就是怎么那字符来拼凑那个8字。我的大概想法是这样:
_
| |
_
| |
_
很勉强我也知道。但这种方法简单。
为了使用字符输出的方式,那么各个边的输出顺序是一定的——2,3,4,1,5,6,0。我们要调整edge_pos的顺。edge_pos[1]将不再是1th,而是3th。新的edge_pos如下。
edge_pos[7]={0x10,0x8,0x4,0x20,0x2,0x1,0x40}。
代码实现
#include<stdio.h>
void show(char);
int main()
{
//将要现示1,2,3,4,5,这五个數字
char input[5] = {1,2,3,4,5};
char num_egdes[10] = {0x5f,0xa,0x76,0x75,0x2d,0x79,0x7a,0x15,0x7f,0x3d};
int i;
for(i=0; i<=4; ++i){
if(input[i]<0 || input[i]>9){
printf("input is wrong!");
break;
}
show(num_egdes[input[i]]);
printf("--input%d\n",input[i]);
}
return 0;
}
void show(char number)
{
char edge_pos[7] = {0x10,0x8,0x4,0x20,0x2,0x1,0x40};
char letter[7] = {'_','|','|','_','|','|','_'};
char position[7] = {'\n',' ','\n','\n',' ','\n','\n'};
int j;
for(j=0; j<=6; ++j){
if(edge_pos[j]&number){
//printf("%d",segment[j]);
//printf("%d",j);
printf("%c",letter[j]);
}
printf("%c",position[j]);
}
printf("over%d",number);
}