1
C语言程序设计
1.11.2.3 10.2.3 案例研究

10.2.3 案例研究

例10-8是一个可以显示存放在ROM_BIOS(基本输入输出子系统)中ASCII码表包括的128个点阵字符的程序。在显示输出时,程序把点阵字符中每个点用二位十六进制数表示,它表示一个点在字符矩阵中的行位置和列位置。矩阵原点定在左上角,例如,字符A、B、C表示为由下列十进制数字组成的点阵。41、42、43分别为这三个字符的ASCII码。

img748

如果采用编辑方法,只保留构成字符的每条直线段的端点坐标,删去所有其他冗余点,如下图所示,其中“*”表示删去的冗余点。

img749

如果按照抄写一个字符时,直线段画出的次序排列这些直线段的起点和终点坐标,就构成了字符的直线段端点表,或称为笔画字形表。

字符A

0x0220,0x2060,0x6061,0x611l,

0X0203,0x0325,0x2565,0x6564,

0x6414,0x4144,0xffff

字符B

0x0005,0x0516,0x1626,0x2635,

0x3532,0x3546,0x4656,0x5665,

0x6560,0x016l,0x0262,0xffff

字符C

0x1605,0x0502,0x0220,0x2040,

0x4062,0x6265,0x6556,0x1151,

0xffff

这里,0x表示十六进制数,0xffff表示笔画结束。

如果要建立一个自己的矢量字符集,则可以对BIOS中的所有字符都进行一次上述的处理。这样就得到了每个字符的编码直线段表。把这些直线段表结合在一起,便形成了软件中使用的笔画(矢量)字符集。

如果把这个字符集放入一个二维数组中,在对数组初始化时,数组包括的128个元素中,每个元素包括36个十六进制数据。对于少于36画的字符,用0xffff数据补足。当要使用某个字符时,可按其ASCII码值去查找。找到字符笔画信息以后,用画线函数按序画出每条直线段就得到了一个字符的笔画字形。画出的A、B和C三个字符的字形如下所示:

img750

下面是采用上述方法建立的一个笔画字符集。128个ASCII码的字型如图10.2.1所示。

img751

图10.2.1 ASCII码字型

例10-8 本程序是一个综合应用结构、位域和联合知识的示例。

程序如下:

img752

img753

img754

程序说明:

1.要打印出BIOS子系统中ASCII码字库包括的128个字符的点阵信息,必须首先解决如何找到存放该字库的起始地址的问题,并能按序从中读出字符的点阵。

BIOS中ASCII码字库在系统中的起始地址为0xF000FA6E,程序的第4行定义CHARBASE为该地址。由于该基地址不在程序的代码段中,因此用通常的近指针(near)不能访问,必须要用长指针(far)跨段访问。关键语句为showchar()函数中的第4行:

  char far*table=(char far*)(CHARBASE+(long)ascii*8L);

table为指向字符的长指针,该语句表示把一个ASCII码值对应的字符的起始字节地址赋予长指针变量table,并把指针指向的数据强行转换成字符类型,以便table能以字节为寻址单位,顺序读出组成一个字符的8行(每行1个字节)点阵信息。有关far指针的使用说明可以在C语言的存储模式中找到。

程序中定义了两个联合变量。联合变量element包括两个结构变量chbytes和bits。bits为位域结构变量,其成员bit0~bit7表示一个字节的第0位~第7位,与chbyte变量的各位相对应。利用bits变量可以访问字符点阵中每一行中各个点的信息。为了把字符点阵中每一个点所在行位置和列位置用十六进制数表示,程序中定义了另一个联合变量chcell,它包括有两个结构变量byte和bits。bits为位域变量,它有两个成员hi和lo,各占一个字节的高四位和低四位,用来以十六进制数方式表示一个点在点阵中的行数和列数。两个联合变量均定义为外部变量。

2.由于字符库中字符点阵信息为8×8矩阵,所以每当按行的次序读一个字符的8行点阵信息时,必须暂存在定义的8×8的matrix数组中,该数组中每一个元素对应字符点阵中的一个点。该元素的行号和列号就是点在点阵中的行坐标和列坐标。

函数showchar()完成了按传递的ASCII码值读出该字符的点阵信息并暂存在matrix数组中的功能。函数中语句element.chbytes.chbtye=*table把table长指针指向的某字符的某一行点阵信息赋给联合成员变量chbyte,然后用位域变量bit0~bit7访问存入chbyte中的每一位。如果某位为1,则在switch语句中,为与该点相对应的matrix数组元素写1,否则写0。在写完一行后,table指针增1,读下一行点阵。在双重for循环语句中完成了matrix全部元素的暂存。

3.程序最后要解决的问题是如何把matrix数组中的信息以十六进制数打印出来。使用for的双重循环,按行主序,顺序读出数组中点阵信息。当为1时,表示该点为字符的一个点,并将该元素的行号和列号赋予hi和lo两个位域成员变量中,即

  chcell.bits.hi=row;

  chcell.bits.lo=7−col;(字节位的存放顺序与字符矩阵x坐标相反)

当用printf()函数将联合变量成员byte按十六进制方式打印输出时,byte取自联合变量中由hi和lo两个位域变量存入的数据,打印出的即是以十六进制数表示的行号和列号。

4.main()函数中,使用for语句,按ASCII码调用函数showchar(),重复执行上述第二和第三个步骤,打印出以行号和列号表示的128个字符的点阵信息,如前A、B和C三个字符所示。