C语言汉字写入问题及Unicode优势.docx
- 文档编号:2186522
- 上传时间:2022-10-27
- 格式:DOCX
- 页数:10
- 大小:218.28KB
C语言汉字写入问题及Unicode优势.docx
《C语言汉字写入问题及Unicode优势.docx》由会员分享,可在线阅读,更多相关《C语言汉字写入问题及Unicode优势.docx(10页珍藏版)》请在冰豆网上搜索。
C语言汉字写入问题及Unicode优势
C语言汉字写入问题及Unicode优势
默认分类2009-06-1309:
22:
13阅读552评论2 字号:
大中小 订阅
常用的字符编码有以下三种:
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编码比如我的一个函数声明是:
voidJustify(HDChdc,PTSTRpText,RECT*prc,intiAlign)
其中的pText是PTSTR类型,PTSTR在WINNT.H中有两个定义(WINNT.H中的这段代码我删掉了中间无关的部分)
#ifdef UNICODE
typedefLPWSTRPTSTR,LPTSTR;//如果是UNICODE编码,则定义PTSTR为LPWSTR类型
#else
typedefLPSTRPTSTR,LPTSTR;//如果是不是UNICODE编码,则定义PTSTR为LPSTR类型
#endif
LPSTR定义为CHAR的指针
LPSWSTR定义为WCHAR的指针
CHAR定义为char类型
WCHAR定义为wchar_t类型
而wchar_t定义为unsignedshort类型,它是16位,两个字节,无符号短整数
"XX"两字的ASCII码分别为:
百:
B0D9度:
B6C8
如果要向test_ascii.txt写入"百"字,则可以这样写代码:
#include
main(){
FILE*fp1;
intascii1,ascii2;
fp1=fopen("test_ascii.txt","wb+");
ascii1=0xB0;
ascii2=0xD9;
fwrite(&ascii1,1,1,fp1);
fwrite(&ascii2,1,1,fp1);
fclose(fp1);
}
我发现TurboC中:
一个int型变量和一个汉字一样,都是占两个字节的,那我们不就可以用一个int型变量来存储一个汉字吗?
答案是可以的:
这样写代码:
#include
main(){
FILE*fp1;
intascii;
fp1=fopen("test_ascii.txt","wb+");
ascii=0xD9*256+0xB0;
fwrite(&ascii,2,1,fp1);
fclose(fp1);
}
关于汉字的ASCII码还可以看我的另一篇博客
URL编码学习(汉字ASCII查询)
一、什么是Unicode
先从ASCII说起,ASCII是用来表示英文字符的一种编码规范。
每个ASCII字符占用1个字节,因此,ASCII编码可以表示的最大字符数是255(00H—FFH)。
其实,英文字符并没有那么多,一般只用前128个(00H—7FH,最高位为0),其中包括了控制字符、数字、大小写字母和其它一些符号。
而最高位为1的另128个字符(80H—FFH)被称为“扩展ASCII”,一般用来存放英文的制表符、部分音标字符等等的一些其它符号。
这种字符编码规则显然用来处理英文没有什么问题。
但是面对中文、阿拉伯文等复杂的文字,255个字符显然不够用。
于是,各个国家纷纷制定了自己的文字编码规范,其中中文的文字编码规范叫做“GB2312—80”,它是和ASCII兼容的一种编码规范,其实就是利用扩展ASCII没有真正标准化这一点,把一个中文字符用两个扩展ASCII字符来表示,以区分ASCII码部分。
但是这个方法有问题,最大的问题就是中文的文字编码和扩展ASCII码有重叠。
而很多软件利用扩展ASCII码的英文制表符来画表格,这样的软件用到中文系统中,这些表格就会被误认作中文字符,出现乱码。
另外,由于各国和各地区都有自己的文字编码规则,它们互相冲突,这给各国和各地区交换信息带来了很大的麻烦。
要真正解决这个问题,不能从扩展ASCII的角度入手,而必须有一个全新的编码系统,这个系统要可以将中文、法文、德文……等等所有的文字统一起来考虑,为每一个文字都分配一个单独的编码。
于是,Unicode诞生了。
Unicode也是一种字符编码方法,它占用两个字节(0000H—FFFFH),容纳65536个字符,这完全可以容纳全世界所有语言文字的编码。
在Unicode里,所有的字符被一视同仁,汉字不再使用“两个扩展ASCII”,而是使用“1个Unicode”,也就是说,所有的文字都按一个字符来处理,它们都有一个唯一的Unicode码。
二、使用Unicode编码的好处
使用Unicode编码可以使您的工程同时支持多种语言,使您的工程国际化。
另外,WindowsNT是使用Unicode进行开发的,整个系统都是基于Unicode的。
如果调用一个API函数并给它传递一个ANSI(ASCII字符集以及由此派生并兼容的字符集,如:
GB2312,通常称为ANSI字符集)字符串,那么系统首先要将字符串转换成Unicode,然后将Unicode字符串传递给操作系统。
如果希望函数返回ANSI字符串,系统就会首先将Unicode字符串转换成ANSI字符串,然后将结果返回给您的应用程序。
进行这些字符串的转换需要占用系统的时间和内存。
如果用Unicode来开发应用程序,就能够使您的应用程序更加有效地运行。
下面例举几个字符的编码以简单演示ANSI和Unicode的区别:
字符AN和ANSI码41H4eHcdbaHUnicode码0041H004eH548cH
三、使用C++进行Unicode编程
对宽字符的支持其实是ANSIC标准的一部分,用以支持多字节表示一个字符。
宽字符和Unicode并不完全等同,Unicode只是宽字符的一种编码方式。
1、宽字符的定义
在ANSI中,一个字符(char)的长度为一个字节(Byte)。
使用Unicode时,一个字符占据一个字,C++在wchar.h头文件中定义了最基本的宽字符类型wchar_t:
typedefunsignedshortwchar_t;
从这里我们可以清楚地看到,所谓的宽字符就是无符号短整数。
2、常量宽字符串
对C++程序员而言,构造字符串常量是一项经常性的工作。
那么,如何构造宽字符字符串常量呢?
很简单,只要在字符串常量前加上一个大写的L就可以了,比如:
wchar_t*str1=L"Hello";
这个L非常重要,只有带上它,编译器才知道你要将字符串存成一个字符一个字。
还要注意,在L和字符串之间不能有空格。
3、宽字符串库函数
为了操作宽字符串,C++专门定义了一套函数,比如求宽字符串长度的函数是
size_t__cdelwchlen(constwchar_t*);
为什么要专门定义这些函数呢?
最根本的原因是,ANSI下的字符串都是以’\0’来标识字符串尾的(Unicode字符串以“\0\0”结束),许多字符串函数的正确操作均是以此为基础进行。
而我们知道,在宽字符的情况下,一个字符在内存中要占据一个字的空间,这就会使操作ANSI字符的字符串函数无法正确操作。
以”Hello”字符串为例,在宽字符下,它的五个字符是:
0x00480x00650x006c0x006c0x006f
在内存中,实际的排列是:
480065006c006c006f00
于是,ANSI字符串函数,如strlen,在碰到第一个48后的00时,就会认为字符串到尾了,用strlen对宽字符串求长度的结果就永远会是1!
4、用宏实现对ANSI和Unicode通用的编程
可见,C++有一整套的数据类型和函数实现Unicode编程,也就是说,您完全可以使用C++实现Unicode编程。
如果我们想要我们的程序有两个版本:
ANSI版本和Unicode版本。
当然,编写两套代码分别实现ANSI版本和Unicode版本完全是行得通的。
但是,针对ANSI字符和Unicode字符维护两套代码是非常麻烦的事情。
为了减轻编程的负担,C++定义了一系列的宏,帮助您实现对ANSI和Unicode的通用编程。
C++宏实现ANSI和Unicode的通用编程的本质是根据”_UNICODE”(注意,有下划线)定义与否,这些宏展开为ANSI或Unicode字符(字符串)。
如下是tchar.h头文件中部分代码摘抄:
#ifdef_UNICODE
typedefwchar_tTCHAR;
#define__T(x)L##x
#define_T(x)__T(x)
#else
#define__T(x)x
typedefcharTCHAR;
#endif
可见,这些宏根据”_UNICODE”定义与否,分别展开为ANSI或Unicode字符。
tchar.h头文件中定义的宏可以分为两类:
A、实现字符和常量字符串定义的宏我们只列出两个最常用的宏:
宏未定义_UNICODE(ANSI字符)定义了_UNICODE(Unicode字符)TCHARcharwchar_t_T(x)xL##x
注意:
“##”是ANSIC标准的预处理语法,它叫做“粘贴符号”,表示将前面的L添加到宏参数上。
也就是说,如果我们写_T(“Hello”),展开后即为L“Hello”
B、实现字符串函数调用的宏
C++为字符串函数也定义了一系列宏,同样,我们只例举几个常用的宏:
宏未定义_UNICODE(ANSI字符)定义了_UNICODE(Unicode字符)_tcschrstrchrwcschr_tcscmpstrcmpwcscmp_tcslenstrlenwcslen
四、使用Win32API进行Unicode编程
Win32API中定义了一些自己的字符数据类型。
这些数据类型的定义在winnt.h头文件中。
例如:
typedefcharCHAR;typedefunsignedshortWCHAR;//wc,16-bitUNICODEcharactertypedefCONSTCHAR*LPCSTR,*PCSTR;
Win32API在winnt.h头文件中定义了一些实现字符和常量字符串的宏进行ANSI/Unicode通用编程。
同样,只例举几个最常用的:
#ifdefUNICODEtypedefWCHARTCHAR,*PTCHAR;typedefLPWSTRLPTCH,PTCH;typedefLPWSTRPTST
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 语言 汉字 写入 问题 Unicode 优势
![提示](https://static.bdocx.com/images/bang_tan.gif)