Chinaunix首页 | 论坛 | 博客
  • 博客访问: 770931
  • 博文数量: 199
  • 博客积分: 3584
  • 博客等级: 中校
  • 技术积分: 2193
  • 用 户 组: 普通用户
  • 注册时间: 2008-05-12 21:18
文章分类

全部博文(199)

文章存档

2018年(6)

2013年(14)

2012年(30)

2011年(28)

2010年(24)

2009年(86)

2008年(11)

分类: C/C++

2010-06-10 17:13:44

在处理套打程序时用到TextOut,但TextOut无法自动换行,只好动手写代码,可是处理到汉字部分时卡住了,搜索网上判断汉字的帖子,都语焉不详,经过一下午的研究,终于整理出一个简单的教程。  
   
其实判断汉字的代码很简单,简单到只有一行就可以了,但不理解汉字编码的基础,这一行代码却万万无法理解。  
   
常用的字符编码有以下三种:  
1、ASCII   只支持英文,全部为8位  
2、DBCS     支持英文和中文,但中文需要两个字节(16位)  
3、UNICODE   支持英文和中文,英文和中文都需要两个字节  
   
ASCII是DOS时代的,无法支持中文。DBCS是Win9x支持的字符集。UNICODE是win2k和xp支持的字符集。  
而汉字的编码目前有GB2312-1980和GB18030-2000,GB2312就是DBCS类型的汉字编码,GB18030就是UNICODE的汉 字编码,当然GB18030兼容GB2312,也就是说GB18030也支持DBCS的字符处理方式。虽然GB18030是2000年后强制执行的国家标 准,但目前使用最多的还是GB2312编码,而且GB2312也足够处理你所用到的汉字了。还有GBK编码是GB2312的增强版。  
   
这里我仅支持GB2312。由于GB2312是中国大陆制定的标准,所以繁体中文并不在GB2312的编码中,如果你的程序需要支持繁体中文,则还需要处理Big5编码。其实也很简单。  
   
下面说一下在C中如何处理GB2312编码的汉字。以VC6.0为例,如果声明变量的类型为wchar_t则是UNICODE编码,如果是char则是DBCS编码比如我的一个函数声明是:  
void   Justify   (HDC   hdc,   PTSTR   pText,   RECT   *   prc,   int   iAlign)          
其中的pText是PTSTR类型,PTSTR在WINNT.H中有两个定义(WINNT.H中的这段代码我删掉了中间无关的部分)  
#ifdef     UNICODE  
typedef   LPWSTR   PTSTR,   LPTSTR; //如果是UNICODE编码,则定义PTSTR为LPWSTR类型  
#else  
typedef   LPSTR   PTSTR,   LPTSTR; //如果是不是UNICODE编码,则定义PTSTR为LPSTR类型  
#endif  
   
LPSTR定义为CHAR的指针  
LPSWSTR定义为WCHAR的指针  
CHAR定义为char类型  
WCHAR定义为wchar_t类型  
而wchar_t定义为unsigned   short类型,它是16位,两个字节,无符号短整数  
   
是UNICODE还是非UNICODE取决于你的编译选项,如果在[工程]-[选项]-[C/C++]的[预处理程序定义]中填入了_UNICODE,那 么程序会用wchar_t指针来定义LPSTR,如果没有_UNICODE,那么程序会用char指针来定义LPSTR,这样带来的区别就是,你接受到的 pText中的字节内容是不一样的,[i服了you]这个字串如果在没有定义_UNICODE的情况下,是8个字节,而在定义了_UNICODE的情况下 是12个字节。反映到程序中就是,如果没有定义_UNICODE,那么就要把英文字符当成1个字节来处理,而汉字字符的编码是采用GB2312编码规范来 的;如果定义了_UNICODE,那么英文字符要当成2个字节来处理,而汉字字符的编码是采用UNICODE编码来的。举例来说,win98不采用 UNICODE编码而采用的是DBCS编码,为了让我的程序既可以在XP下运行又可以在Win98下运行,我没有定义_UNICODE。这样我的程序代码 就要把字符串当成DBCS编码来处理,也就是英文字符是1个字节,中文字符是2个字节,中文编码采用GB2312编码。用Justify来说明:  
我给pText传递来[你]这个汉字,那么pText应该有两个字节来存放[你]这个字,设置段点来读一下pText的内容。  
void   Justify   (HDC   hdc,   PTSTR   pText,   RECT   *   prc,   int   iAlign)  
{  
static   TCHAR   szText[]   =   {TEXT   ("你")}   ;  
   
pText=szText;  
}  
设断调试会发现*pText=-60,怎么会这样呢,原因是没有按unsigned   char来转换*pText的值,修改代码如下:  
void   Justify   (HDC   hdc,   PTSTR   pText,   RECT   *   prc,   int   iAlign)  
{  
static   TCHAR   szText[]   =   {TEXT   ("你")}   ;  
unsigned   char   sqChar[20]; //这个变量就是为了强制转换类型用的  
   
pText=szText;  
sqChar[0]=*pText;  
sqChar[1]=*(pText+1);  
}  
这时下断查看sqChar[0]=196,sqChar[1]=227就对了,为什么呢,因为它和GB2312的编码是一样的。  
GB2312-80编码的编码范围是高位0xa1-0xfe,低位是   0xa1-0xfe   ,其中汉字范围为   0xb0a1   和   0xf7fe,如果只是简单地判断汉字,则只要查看高字节是否大于等于0xa1就可以了,还有就是,全角字符的高字节统统等于0xa3,所以很容易可以区 别出全角字符来。  
   
如果你希望你的程序能支持到GB18030,那么就去找GB18030的规范来看看。  
   
网上有很多判断汉字的说法,你只要记住,你要支持的编码是哪个?GB2312、GBK、GB18030?每个编码有自己的编码范围或者规范,网上之所以有 不同的说法,正是因为他们互相说的不是同一种编码方式。我这里说的是GB2312的编码,如果你的程序要编译成支持UNICODE的话,那么这段代码就要 修改成对应UNICODE规范的代码了。  
   
附简单的测试汉字、全角字符、英文的程序:  
   
//test.c  
//源代码作者:夏克     
//新建Win32   Application工程,把test.c加入,运行,试着修改szText的值,来观察代码效果  
   
#include     
   
int   WINAPI   WinMain   (HINSTANCE   hInstance,   HINSTANCE   hPrevInstance,  
PSTR   szCmdLine,   int   iCmdShow)  
{  
static   TCHAR   szText[]   =   {TEXT   ("i服,了。uy")}   ;  
PTSTR   pText;  
int   i;  
unsigned   char   sqChar[20];  
   
pText=szText;  
while   (*pText   !=   '\0')  
{  
i=IsGB(pText);  
   
switch(i)  
{  
case   0:  
pText++;  
MessageBox   (NULL,   TEXT   ("发现数字、英文字符或英文标点"),   TEXT   ("Hello"),   0);  
break;  
case   1:  
pText++;  
pText++;  
MessageBox   (NULL,   TEXT   ("发现全角字符"),   TEXT   ("Hello"),   0);  
break;  
case   2:  
pText++;  
pText++;  
MessageBox   (NULL,   TEXT   ("发现汉字"),   TEXT   ("Hello"),   0);  
break;  
}  
}  
   
return   0   ;  
}  
   
int   IsGB(PTSTR   pText)  
{  
unsigned   char   sqChar[20];  
sqChar[0]=*pText;  
if   (sqChar[0]>=0xa1)  
if   (sqChar[0]==0xa3)  
return   1; //全角字符  
else  
return   2; //汉字  
else  
return   0; //英文、数字、英文标点  
}

汉字在电脑中的编码处理简介 GB2312/GBK/GB18030/BIG5
中文字符编码简介 GB2312/GBK/GB18030/BIG5

1 GB2312-80

GB2312码是中华人民共和国国家汉字信息交换用编码,全称《信息交换用汉字编码字符集——基本集》,由国家标准总局发布,1981年5月1日实施,通行于大陆。新加坡等地也使用此编码。

GB2312收录简化汉字及符号、字母、日文假名等共7445个图形字符,其中汉字占6763个。GB2312规定“对任意一个图形字符都采用两个字节表示,每个字节均采用七位编码表示”,习惯上称第一个字节为“高字节”,第二个字节为“低字节”。

GB2312 将代码表分为94个区,对应第一字节;每个区94个位,对应第二字节,两个字节的值分别为区号值和位号值加32(2OH),因此也称为区位码。01-09 区为符号、数字区,16-87区为汉字区,10-15区、88-94区是有待进一步标准化的空白区。GB2312将收录的汉字分成两级:第一级是常用汉字 计3755个,置于16-55区,按汉语拼音字母/笔形顺序排列;第二级汉字是次常用汉字计3008个,置于56-87区,按部首/笔画顺序排列。故而 GB2312最多能表示6763个汉字。

GB2312的编码范围为2121H-777EH,与ASCII有重叠,通行方法是将GB码两个字节的最高位置1以示区别。

2 GBK

GB2312 -80仅收汉字6763个,这大大少于现有汉字,随着时间推移及汉字文化的不断延伸推广,有些原来很少用的字,现在变成了常用字,例如:朱镕基的“镕” 字,未收入GB2312-80,现在大陆的报业出刊只得使用(金+容)、(金容)、(左金右容)等来表示,形式不一而同,这使得表示、存储、输入、处理都 非常不方便,对于搜索引擎等软件的构造来说也不是好消息,而且这种表示没有统一标准。从我们对人民日报98年数据的处理过程中,得出这样的经验:回填外字 最困难的就是如何得到这种表示方法的集合。

为了解决这些问题,以及配合UNICODE的实施,全国信息技术化技术委员会于1995年12 月1日《汉字内码扩展规范》。GBK向下与GB2312 完全兼容,向上支持ISO 10646国际标准,在前者向后者过渡过程中起到的承上启下的作用。GBK 亦采用双字节表示,总体编码范围为8140-FEFE之间,首字节在81-FE之间,尾字节在40-FE之间,剔除XX7F一条线。

GBK共收入21886个汉字和图形符号,包括:

* GB2312中的全部汉字、非汉字符号。
* BIG5中的全部汉字。
* 与ISO 10646相应的国家标准GB13000中的其它CJK汉字,以上合计20902个汉字。
* 其它汉字、部首、符号,共计984个。

微软公司自Windows 95 简体中文版开始支持GBK代码,但目前的多数搜索引擎都不能很好地支持GBK汉字。

GBK编码区分三部分:

* 汉字区 包括
GBK/2:OXBOA1-F7FE, 收录GB2312汉字6763个,按原序排列;
GBK/3:OX8140-AOFE,收录CJK汉字6080个;
GBK/4:OXAA40-FEAO,收录CJK汉字和增补的汉字8160个。
* 图形符号区 包括
GBK/1:OXA1A1-A9FE,除GB2312的符号外,还增补了其它符号
GBK/5:OXA840-A9AO,扩除非汉字区。
* 用户自定义区
即GBK区域中的空白区,用户可以自己定义字符。


3 GB18030

GB18030 是最新的汉字编码字符集国家标准, 向下兼容 GBK 和 GB2312 标准。 GB18030 编码是一二四字节变长编码。一字节部分从 0x0~0x7F 与 ASCII 编码兼容。 二字节部分, 首字节从 0x81~0xFE, 尾字节从 0x40~0x7E 以及 0x80~0xFE, 与 GBK标准基本兼容。 四字节部分, 第一字节从 0x81~0xFE, 第二字节从 0x30~0x39, 第三和第四字节的范围和前两个字节分别相同。 四字节部分覆盖了从 0x0080 开始, 除去二字节部分已经覆盖的所有 Unicode 3.1 码位。也就是说, GB18030 编码在码位空间上做到了与 Unicode 标准一一对应,这一点与 UTF-8 编码类似。

目前最新的 glibc 2.2.x 系列已经全面支持了 GB18030 Locale 和 GB18030 与 UCS-4 之间的编码转换, 也就是说在系统层上 Linux 已经可以支持 GB18030 标准了。 下面问题的关键就是怎样让 XFree86 窗口系统也支持 GB18030 标准。

4 BIG5

BIG5是通行于台湾、香港地区的一个繁体字编码方案。虽然存在一些瑕疵,但广泛应用于电脑行业,尤其是互联网中,从而成为一种事实上的行业标准。

1983年10月,台湾国家科学委员会、教育部国语推行委员会、中央标准局、行政院共同制定了《通用汉字标准交换码》,后经修订于1992年5月公布,更名为《中文标准交换码》,BIG5是台湾资讯工业策进会根据以上标准制定的编码方案。

BIG5码是双字节编码方案,其中第一个字节的值在OXAO-OXFE之间,第二个字节在OX40-OX7E和OXA1-OXFE之间。

BIG5收录13461个汉字和符号,包括:

* 符号408个,编码位置A140-A3BE
* 常用字5401个,编码位置A440-C67E,包括台湾教育部颁布的《常用国字标准字体表》的全部汉字4808个,台湾教科书常用字587个,异体字6个。
* 次常用字7652个,编码位置C940-F9D5,包括台湾教育部颁布的《次常用国字标准字体表》的全部汉字6341个,《罕用国字标准字体表》中使用频率较高的字1311个。


来自:%D5%D4%B7%F6%B7%E7/blog/item/70db3afd03f5101f09244df9.html

阅读(7307) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~