汉字内码漫谈

来源:互联网 发布:提问的软件 编辑:程序博客网 时间:2024/04/30 15:52
   不用通常的汉字输入法能输入汉字吗?在英文状态下能打印出汉字吗?请看下面两个实验:
  实验一·启动UCDOS汉字系统,在“英文”输入状态下,将副键盘切换成数字输入状态,然后在系统提示符后面作如下操作:
  左手按住Alt,右手依次敲副键盘上的1、7、6,松开Alt键;再按住Alt键,依次敲副键盘上的1、6、1,松开Alt键,这时屏幕光标处出现了一个“啊”字。
  实验二·打开自带汉字库的打印机(如LQ150K,LQ1600K等),启动DOS(不启动任何汉字系统),在系统提示符后面作如下操作:
  ①键入命令: COPY CON PRN←┘
  ②同实验一中输入“啊”的操作;
  ③敲回车键,再敲F6键,再敲回车键。
  这时打印机打印出一个“啊”字。
  在实验一中,我们在汉字系统的英文输入状态(注意,不是在拼音、五笔字型等汉字输入状态)下输入了汉字;实验二中,在英文状态下打印出了汉字。道理何在呢?
  原来,计算机上使用的汉字有两类代码,一类叫外码,用来输入汉字,如拼音码、郑码、五笔字型码等。由于人们不断寻求更佳的汉字输入法,因此外码也就层出不穷。不同的外码规则也不同,如果计算机内部存储汉字时,也采用这些五花八门的编码,势必使汉字系统过于复杂。因此,不论用什么输入法输入的汉字,在存入存储器时,都将它的外码转换成一种统一的代码,这就是汉字内码。
  一个汉字的内码由两个字节组成。汉字内码与区位码之间有一个简单的数学关系:
  内码第一字节=区码+160
  内码第二字节=位码+160
  比如,查区位码表知道,“啊”字在16区01位,它的内码为:
  第一字节=16+160=176
  第二字节=1+160=161
  这下就明白了,在前面的两个实验中,我们是利用Alt键加副键盘能输入字符代码的功能,直接用内码输入了汉字“啊”。
  我们知道,英文字符的代码ASCII只用一个字节表示。为什么一个汉字要用两个字节来表示呢?原来一个字节(8位二进制数)能表示的最大整数范围是0~255,也就是说最多能表示256种不同的状态,这用于表示几十个英文字符足够了。但是汉字有成千上万个,所以至少要用两个字节(16位二进制数)来编码。两个字节最多可有65536种不同的编码。
  由于大多英文软件只处理单字节对象,而汉字内码又是双字节的。在汉字系统中使用英文软件来处理汉字时就会带来一些问题。比如我们用DOS6.2中的EDIT编辑一个文本文件,要删掉其中的一个汉字时,要敲两次删除键才能删掉。若是只删了一下,后面的汉字就变得面目全非了。道理很简单:删一下,只删掉了汉字内码的一个字节,剩下的一个字节和下一个汉字的头一个节就构成了另一个汉字或符号的内码,于是就显示出和这个内码对应的汉字或符号。依次错位,后面的汉字就全变了。
  在汉字系统中使用英文软件还会带来另一个问题:由于在原来的英文系统中规定大于127的代码用来代表一些特殊符号,如英文的制表符、欧洲其它文字的字母等。而汉字的内码的每个字节的值都大于127,这样,即使是在汉字系统中,计算机在遇到汉字内码时可能会分不清是汉字还是其它特殊符号。这是我们在汉字系统中运行有些英文软件时会出现怪字或怪符号的原因。目前较流行的汉字系统都在努力改进,力争能分辨出汉字内码和特殊字符的代码,但仍难免疏漏。你可作一个实验:在汉字系统(如常用的UCDOS)中执行DOS命令TREE,在显示出来的结果中就会出现怪字,解决的方法很简单:暂时转到英文显示状态(不用退出汉字系统,如在UCDOS中按Ctrl-F7即可),原来英文系统中的特殊符号就不会被错认成汉字了。
  明白上述道理,也不难理解为什么在英文状态下显示的汉字是全是一些如“天书”的怪符号。因为在英文状态下所有的字符代码均不会被认为是汉字的内码,其值大于127的汉字内码都被当成特殊字符了。
  顺便说一下,我们常用的汉字系统的汉字内码为国标码(或异型国标码),而港台地区流行的汉字系统则采用的是另一种汉字内码──BIG-5码,由于内码不同,虽然都是汉字系统,却互不兼容。为此,一些两种内码转换的工具程序应运而生,如UCDOS中的实用程序CONVERT。但由于国标码与BIG-5码定义的汉字并非──对应的关系,因此这些转换程序不能百分之百地转换所有汉字,有些还得靠手工辅助完成。
  最后给出两个应用汉字内码的BASIC小程序。
  程序一利用区位码与内码的关系,输出区位码表的任意部分。这个程序中倒数第四行是关键的一句,其中的CHR$(i + 160) +CHR$(j + 160)将第i区第j位的汉字转换成汉字内码并以连续两个字节输出一个汉字。
  程序二将一串数字转换成全角的数字字符。区位码表中的全角符号与汉字只是所在的区不同,而内码规则是完全相同的。全角的数字字符“0”的区位码是0316、“1”的区位码是0317……,程序中的第三行正是据此将半角数字的ASCII码转换成汉字内码输出。
  这两个程序在QBASIC、True BASIC、Turbo BASIC中都能通过,运行时可在UCDOS等汉字系统中进行。
  
  程序一清单
  REM 打印区位码表程序
  PRINT
  INPUT "请输入起始区号,结束区号"; qu1, qu2
  INPUT "请输入起始位号,结束位号"; wei1, wei2
  REM 打印位号
  PRINT " ";
  FOR i = wei1 TO wei2
   PRINT " ";
   PRINT USING "##"; i;
  NEXT i
  PRINT
  REM打印区位码表(局部或全部)
  FOR i = qu1 TO qu2
   PRINT USING "##"; i;
   PRINT " ";
   FOR j = wei1 TO wei2
    PRINT CHR$(i + 160) + CHR$(j + 160) + " ";
   NEXT j
   PRINT
  NEXT I
  
  程序二清单
  INPUT "请输入一串数字"; n$
  FOR i = 1 TO LEN(n$)
   PRINT CHR$(3 + 160) + CHR$(ASC(MID$(n$, i, 1)) - ASC("0") + 16 + 160);
  NEXT i
原创粉丝点击