汉字内码与
GB
码
C
程序实现
Lanno Cheecke 2006-8-24
// HZEncode.cpp : Defines the entry point for the console application.
//
/*
参考文献:
汉字的编码和表示
1
)汉字交换码(国标码)
汉字交换码(国标码)主要用于汉字信息交换。
国标码:以国家标准局
1980
年颁布的《信息交换用汉字编码字符集
"
基本集》(代号为
GB2312 80
)规定的汉字交换码作为国家标准汉字编码。
GB2312 80
中共有
7445
个字符符号:
汉字符号
6763
个
一级汉字
3755
个(按汉语拼音字母顺序排列)
二级汉字
3008
个(按部首笔划顺序排列)
非汉字符号
682
个
GB2312 80
规定,所有的国标码汉字及符号组成一个
94 94
的方阵。在此方阵中,每一行称为一个
"
区
"
,每一列称为一个
"
位
"
。这个方阵实际上组成一个有
94
个区(编号由
01
到
94
),每个区有
94
个位(编号由
01
到
94
)的汉字字符集。
一个汉字所在的区号和位号的组合就构成了该汉字的
"
区位码
"
。其中,高两位为区号,低两位为位号。这样区位码可以唯一地确定某一汉字或字符;反之,任何一个汉字或符号都对应一个唯一的区位码,没有重码。
区位码分布情况如下:
区
号
内
容
1
区
键盘上没有的各种符号
2
区
各种序号
3
区
键盘上的各种符号(按中文方式给出)
4 -5
区
日文字母
6
区
希腊字母
7
区
俄文字母
8
区
标识拼音声调的母音及拼音字母名称
9
区
制表符号
10- 15
区
未用
16-55
区
一级汉字(按拼音字母顺序排列)
56- 87
区
二级汉字(按部首笔划顺序排列)
88- 94
区
自定义汉字
由上可以看出,所有汉字与符号的
94
个区,可以分为四个组:
①
1 -15
区:为图形符号区。其中
1 9
区为标准符号区;
10 15
区为自定义符号区。
②
16 -55
区:为一级汉字区,包含
3755
个汉字。这些区中的汉字按汉语拼音顺序排序,同音字按笔画顺序列出。
③
56 -87
区:为二级汉字区,包含
3008
个汉字。这些区中的汉字是按部首笔划顺序排序的。
④
88 -94
区:为自定义汉字区。
国标码规定,每个汉字(包括非汉字的一些符号)由
2
字节代码表示。每个字节的最高位为
0
,只使用低
7
位,而低
7
位的编码中又有
34
个适用于控制用的,这样每个字节只有
27 - 34 = 94
个编码用于汉字。
2
个字节就有
94 94=8836
个汉字编码。在表示一个汉字的
2
个字节中,高字节对应编码表中的行号,称为区号;低字节对应编码表中的列号,称为位号。
汉字国标码的范围用二进制表示是:
00100001 00100001 01111110 01111110 (1+32)10 (1+32)10 (94+32)10 (94+32)10 7
位
ASCII
码是
128
个字符组成的字符集。其中编码值
0 31
(
00000000 00011111
)不对应任何印刷字符,通常称为控制符,用于计算机通信中的通信控制或对计算机设备的功能控制。编码值
32
(
00100000
)是空格字符
SP
。编码值
127
(
1111111
)是删除字符
DEL
。
汉字国标码的起始二进制位置选择
00100001
即
(33)10
是为了跳过
ASCII
码的
32
个控制字符和空格字符。所以,汉字国标码的高位和低位分别比对应的区位码大
(32)10
或
(00100000)2
或
(20)H
,即:
国标码高位
=
区码
+ 20H
(
H
表示十六进制)
国标码低位
=
位码
+ 20H
2)
汉字机内码(内码)(汉字存储码)
汉字机内码(内码)(汉字存储码)的作用是统一了各种不同的汉字输入码在计算机内部的表示。
为了将汉字的各种输入码在计算机内部统一起来,就有了专用于计算机内部存储汉字使用的汉字机内码,用以将输入时使用的多种汉字输入码统一转换成汉字机内码进行存储,以方便机内的汉字处理
汉字机内码是在计算机内部存储、处理的代码。计算机既要处理汉字,又要处理英文。因此计算机必须能区别汉字字符和英文字符。英文字符的的机内码是最高为为
0
的
8
位
ASCII
码。为了不与
7
位
ASCII
码发生冲突,把国标码每个字节的最高位由
0
改为
1
,其余位不变的编码作为汉字字符的机内码。
汉字机内码的范围用二进制表示是:
10100001 10100001 11111110 11111110
机内码的高位和低位比对应的国标码的高位和低位大
(128)10
或
(10000000)2
或
(80)H
即:
机内码高位
=
国标码高位
+ 80H
机内码低位
=
国标码低位
+ 80H
又因为:
国标码高位
=
区码
+ 20H
国标码低位
=
位码
+ 20H
所以:
机内码高位
=
区码
+ A0H
机内码低位
=
位码
+ A0H
也就是说,机内码高位和机内码低位分别比对应的区码和位码大
(160)10
或
(10100000)2
或
(A0)H
例如:汉字
"
啊
"
的区位码为
"1601"
,其中区码为
(16)10
或
(10)H
,位码为
(01)10
或
(01)H
。
则:
机内码高位
= 10H + A0H = B0H
机内码低位
= 01H + A0H = A1H
所以:
机内码
= B0A1H
<!--[if !supportEmptyParas]--> <!--[endif]-->
3)
汉字输入码(外码)
汉字输入码(外码)是为了通过键盘字符把汉字输入计算机而设计的一种编码。
英文输入时,相输入什么字符便按什么键,输入码和机内码一致。汉字输入时,可能要按几个键才能输入一个汉字。
汉字输入方案有成百上千个,但是这千差万别的外码输入进计算机后都会转换成统一的内码。
汉字输入方案大致可分为以下
4
种类型:
(
1
)
音码:如全拼、双拼、微软拼音等
(
2
)
形码:如五笔字型、郑码、表形码等
(
3
)
音形码:如智能
ABC
、自然码等
(
4
)
数字码:如区位码、电报码等
4)
汉字字形码(输出码)
汉字字形码(输出码)用于汉字的显示和打印,是汉字字形的数字化信息。
汉字的内码是用数字代码来表示汉字,但是为了在输出时让人们看到汉字,就必须输出汉字的字形。在汉字系统中,一般采用点阵来表示字形。
16 *16
汉字点阵示意
16 * 16
点阵字形的字要使用
32
个字节(
16 * 16/8= 32
)存储,
24 * 24
点阵字形的字要使用
72
个字节(
24 * 24/8=72
)存储。
一般来说,表现汉字时使用的点阵越大,则汉字字形的质量也越好,当然每个汉字点阵所需的存储量也越大。
5)
汉字地址码
汉字地址码是指汉字库(这里主要指整字形的点阵式字模库)中存储汉字字形信息的逻辑地址。在汉字库中,字形信息都是按一定顺序(大多数按标准汉字交换码中汉字的排列顺序)连续存放在存储介质上的,所以汉字地址码也大多是连续有序的,而且与汉字内码间有着简单的对应关系,以简化汉字内码到汉字地址码的转换。
*/
<!--[if !supportEmptyParas]--> <!--[endif]-->
#include "stdafx.h"
#include "HZEncode.h"
<!--[if !supportEmptyParas]--> <!--[endif]-->
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define UNICODE
#define _UNICODE
/
// The one and only application object
<!--[if !supportEmptyParas]--> <!--[endif]-->
CWinApp theApp;
<!--[if !supportEmptyParas]--> <!--[endif]-->
using namespace std;
unsigned short* ptr;
char* pszHZ = "啊";
byte bt[] = {0xc4,0xe3,0xBA,0xC3};//“你好”的机内码
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
<!--[if !supportEmptyParas]--> <!--[endif]-->
// initialize MFC and print and error on failure
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// TODO: change error code to suit your needs
cerr << _T("Fatal Error: MFC initialization failed") << endl;
nRetCode = 1;
}
else
{
for (int i = 16;i <= 55; i++)
{
byte Temp[3];
Temp[2] = 0;
Temp[0] = i + 0xA0;
for (int j = 1;j < 94;j++)
{
Temp[1] = j + 0xA0;
cout << (LPCTSTR) Temp;
}
cout << endl;
}
<!--[if !supportEmptyParas]--> <!--[endif]-->
}
<!--[if !supportEmptyParas]--> <!--[endif]-->
system("pause");
return nRetCode;
}
<!--[if !supportEmptyParas]--> <!--[endif]-->