stdlf
分类:
2010-03-19 10:37:14
有很多这样的编者,他们永远不会在一本书中详尽地叙述一个看起来非常简单的例子。因为这样看来象是在浪费纸张。但是初学者永远是有的,在碰到困难的时候,他们很需要得到耐心的指导和帮助,而事实上他们所看到的都是些“高层次”的内容。每个编者都是从初学者开始的,但他们开始编书的时候,往往不屑于那些细节的问题,这是令读者很苦恼的。
汉字是怎样写到屏幕上来的,中断能用来干什么,还有怎样让你的程序支持鼠标的操作,在此我们开辟了系列讲座:汉字的处理技术、中断的处理技术、鼠标的处理技术,内容由浅至深,环环相扣,很符合初学者的特点。每一章节都提供有很好的例程,并且附上程序的真实运行结果。建议读者要读懂它们,并且能够“临摹”出一些类似的程序来。
关于本文的读者对象,要求能熟悉C语言的基本语法以及关于文件的基本操作,还有一点UCDOS的操作。“程序永远没有结束的时候”。希望读者朋友们能相互切磋,共同提高。
许多读者朋友学会了基本的C语言编程以后,就开始对汉字技术产生了兴趣。本篇分别从中文状态、西文状态、文本方式、图形方式四种情形进行汉字处理的介绍。
一、中文状态下的汉字处理
1.第一个汉字处理程序
学习C语言首先都是从著名的“Hello world!”程序起步,它的程序清单如下:
/*test01l. c*/
main( )
{
printf("Helloworld! \n");
}
以下是它的汉化版:
/*test02. c/
main()
{
printf("你好,世界!\n");
}
这个程序是合法的,而且非常简单,但编辑、编译工作常常令初学者感到迷惑。实际上,这些工作必须按以下步骤进行:
① 运行UCDOS(或其他汉字系统);
② 运行TC;
③ 编辑test02. c;
④ 编译、运行。
2. UCDOS为我们干了什么
编译运行以下程序:
/*test03.c/
main()
{
printf("%c%c! \n" 0xc5 0xde);
}
我们在UCDOS下,再运行同样的程序,它将得到另一种结果:
原先看似文静的test03. c变得如此面目可憎。
UCDOS到底为我们干了什么?我们通常所说的一个汉字占两个字节究竟是什么含义?汉字的机内码又是什么意思?下面就详细谈谈它。
众所周知,一个ASCII字符占一个字节,它的数值从0到255。UCDOS作为一个操作系统,它应该允许用户通过ASCII码来调用相应的字符。那么这样一来,汉字字符将如何与ASCII字符区别开来呢?
实际上,仔细观察ASCII字符表,从第161个字符开始,后面的字符并不经常为用户所使用。UCDOS充分利用这一特性,将161-255之间的数值空间作为汉字的标识码。既然255-161 = 94不能满足汉字容量的要求,就将每两个字符并在一块(即一个汉字占两个字节),显然,94* 94 =8836基本上已经满足了常用汉字个数的要求。
这样,在UCDOS环境下,对于字符的处理就有所不同。如果连续两个码值都大于160的话,那么则认为是汉字;否则都认为是ASCII码。
以上的描述可以用程序test04.c来模拟:
/*test04.c/ #include main() { int flag=0; char str [15] = "Zero青春工作室"; unsigned char*sp=str; while(*sp) { if(*sp> 0xa0)//0xa0=160,汉字地代 { if(! flag) flag++; else { putchar('\l'); flag--; } } else putchar('$'); sp++; } }
test04. c的目的在于搜索str字符串,当发现汉字就输出一张“笑脸”,否则就输出“$”符。
由于一个汉字占用两个字节,这两个字节的数值就称为该汉字的机内码(分别称为高字节内码和低字节内码)。test03.c中的“呸”字的机内码即为Oxc5de,这就是在中文环境下test03.c破口骂人的原因。
汉字的机内码与通常所讲的区位码是有区别的,这点在以后的内容中将会谈到。
3.支持各种汉字输入法
许多读者对这个问题很敏感,也很希望自己编制出来的程序能支持各种汉字输入法,但看了以下的内容,可能会有所失望。
因为各种输入法都是一个TSR(内存驻留)程序,它们驻留在内存里面,都是些很好的工具(当然还有些不足,这点下一小节再谈)。一旦你的“热键”激活了它,它们就会为你工作。所以从某种意义上讲,那些吹嘘“本软件支持各种流行的输入法”只是一种骗局,事实上是各种汉字输入法支持了这些软件。
既然TSR程序为我们做好了一切,我们就可以编写“支持各种汉字输入法”的程序了。
/*test05.c/
#include
main()
{
char str[80];
gotoxy(1, 20);
printf("请输入:\n");
scanf("%s", str);
}
运行UCDOS,这时屏幕最下面一行是“输入法提示行”。运行test05. exe,开始输入字符,在输入过程中,如果切换输入法至中文输入状态,即可输入汉字。
4.图形状态下汉字处理
图形状态下的汉字处理如同文本状态下一样简单可行:
/*test06.c/
#include
#include
main()
{
int gd=VGA, gm=VGAHI;
char str[80];
initgraph(&gd, &gm, "");
circle(200, 200, 50);
line(0, 470, 640, 470);
gotoxy(1, 20);
printf("请输入:\n");
scanf("%s", str);
closegraph();
}
编译运行test06. exe,进入图形状态后,出现中文提示和一条直线,可能找不到“输入法提示行”。敲击右Shift键呼出它,如同test05. c,可以用不同的输入法输入内容。
一切看起来很正常,但事实上输入法内存驻留程序还是有不足的,这可能是TSR程序的体积限制带来的问题。如果读者在输入的同时,敲击右Shift键就会隐去“输入法提示行”但是并没有因此而使原先画的一条直线再现出来,也就是说“输入法提示行”吃掉了它。不过,对于简单的程序实现,这并不太重要。否则,就必须特别地为之编写相应的中断处理程序(见第二篇)来弥补这个缺点。
5.系统环境的自动识别
我们很有可能编写过如下这样的程序:
/*test07. c*/
main()
{
printf(" \n祝可爱的李辉妹妹生日快乐!");
}
test07.c在中文环境下运行时,一切正常,而且带着温馨的祝福。然而,如果一不小心在西文DOS下运行了这个程序,我们完全可以想象,结果是多么地令人不愉快。
为了避免类似的难堪,我们必须编写出适应性很强的代码,它必须能自动地识别当前的系统环境,然后做出明智的做法,就象UCDOS的SETUP一样。
UCDOS一工作,它就会在某一个隐蔽的位置作了一个标记,因为它本身带有的那些应用程序也必须用到它。这个隐蔽的标记可以利用0x2f号中断访问到。
改进的“问候程序”如下:
/*test08.c/
#include
main()
{
char loaded;
_AX= 0xdb00;
geninterrupt(0x2f);
loaded=(_AL==0xff&&_BX==0x5450&&_DX==5);
if(loaded)
printf("\n祝可爱的李辉妹妹生日快乐!");
else
printf("\nHappy birthday to dear LiHui!");
}
在中文环境下输出:
在西文环境下输出:
显然,不管在中文还是在西文环境下,它都不再会令你失望了(当然,糟糕的英语除外)。
本文曾经发表于《电脑爱好者》期刊杂志98年2期,版权CFan所有。