昨天写完几篇文章后觉得意犹未尽,我想想了,既然字库文件是二进制文件,完全可以转化为十六进制,存储在数组中,这样在寻找字符时就不用操作文件了,直接在内存中获取。
经过一番调研,证明这个思路是对的,是具有可行性的,同时也具有很强的实践意义的。(此为胡扯,不可相信)
这次写的代码全部使用C语言标准库中与文件有关的函数,所涉及的函数均以“f”开头,做到了平台无关性,为跨平台打下基础,具有很强的移植性。不过由于时间、精力、金钱、能力、水平关系,没有在vc6.0、vs2008、MiniGW、Dev c++下一一测试。
无特别说明,文中说的“ASCII字库”是指ASC16文件,完整给出了0~255的字符。“汉字字库”是指HZK16,包含了GB2312编码中的字符。
啥也别说,直接上代码,完整的代码如下:
1 | #include <stdio.h> |
代码毫无算法可言,如果一定要说点什么,步骤大约是这样的:
1、打开字库文件,创建字库数组头文件,使用的函数为fopen。
2、获取字库文件长度大小,使用fseek和ftell函数。
3、由于ASCII字库中ASCII码占16个字节的空间,因此以16字节为单位,逐一读取该文件的中数据。读取完整的字库文件条件为:
1 | for (i = 0; i < len; i += 16) |
但是ASCII中只有区区96个可打印的字符,因此为节省空间起见,就将那么字符存储起来,条件为:
1 | for (i = 0x20*16; i < len/2; i+=16) |
至于为什么,前面强调了“实践性”,当然是实践得到的。由于ASC16包含了0255个,一半即为0127,可打印字符从0x20处开始,即0x20是第一个可打印的字符——虽然它是空格。有了循环条件,就可以合理地读取,保存到文件中了。使用fseek定位某个字符的偏移,使用fread读取该偏移处的16个字符。之后再使用fprintf写入另一文件中。当然可以每次读取一个字节,写入一个字节,也可以读取32个字节,写入32个字节。至于
1 | fprintf(fp_c, "/* %d 0x%x ' %c ' *\n", i/16, i/16, i/16); |
主要是打印这个ASCII的十进制、十六进制以及它本身显示的字符,从后面三个数可以看出,这几个东西其实是一个东西,本质是一样,只不过表现形式不一样而已。 至于汉字字库,一样的道理,只是以32个字节为一单位。 以ASCII为例,下面是生成的ascii16.h文件的部分内容:
1 | /******************************************************/ |
上面格式不太整齐,原因在前面的文章已经说了,其实在编辑器中是非常整齐大方的。
研究成果已经出来了,那么要看看它能不能在实践中经受得起考验。
下面是是昨天经过修改后,并使用上面程序生成的英文字库数组及中文字库数组用ncurses来显示的完整代码:
1 | #include <stdio.h> |
至于代码中为什么将y放到前面,是因为这样更能直观表示我们对面的屏幕的坐标,比如
1 | display_font(1, 0, incode); |
就表明了在第1行,第0列显示incode数组的字符。
经过修改后的代码比较整洁,效果与前面的一致,虽然没有了文件的操作,但是占用内存空间比较大,这个代码编译得到的可执行文件大小有271KB,算比较大的了。在操作文件及占用空间之间如何选择,就仁者见仁,智者见智了。
(实践证明,本研究符合当初的设计,经过一段时间的使用,达到预期目标,在生产实践中具有很强的指导意义及教育意义。为将来进一步研究打下牢固的基础。)
至此,近来的研究暂时告一段落,以后搞些什么,再说吧。