cc++输出汉字
1. 使⽤TCHAR类型,定义在tchar.h中
#include <tchar.h>
#include <stdio.h>
int main()
{
TCHAR s[] = "你";
printf("%s /n",s);
return 0;
}
2.关于C++中⽂字符的处理
⼀ 引⼊问题
代码 wchar_t a[3]=L”中国”,编译时出错,出错信息为:数组越界。但wchar_t 是⼀个宽字节类型,
数组a的⼤⼩应为6个字节,⽽两个汉字的的unicode码占4个字节,再加上⼀个结束符,最多6个字节,所以应
该不会越界。难道是编译器出问题了?
⼆ 解决引⼊问题所需的知识
主要需两⽅⾯的知识,第⼀个为字符尤其是汉字的编码,以及语⾔和⼯具的⽀持情况,第⼆个是vc/c++中
MutiByte Charater Set 和 Wide Character Set有关内存分配的情况.
三 汉字的编码⽅式及在vc/c++中的处理
1.汉字编码⽅式的介绍
对英⽂字符的处理,7位ASCII码字符集中的字符即可满⾜使⽤需求,且英⽂字符在计算机上的输⼊及
输出
也⾮常简单,因此,英⽂字符的输⼊、存储、内部处理和输出都可以只⽤同⼀个编码(如ASCII码)。
⽽汉字是⼀种象形⽂字,字数极多(现代汉字中仅常⽤字就有六、七千个,总字数⾼达5万个以上),且字
形复杂,每⼀个汉字都有"⾳、形、义"三要素,同⾳字、异体字也很多,这些都给汉字的的计算机处理带来了很
⼤的困难。要在计算机中处理汉字,必须解决以下⼏个问题:⾸先是汉字的输⼊,即如何把结构复杂的⽅块汉
字输⼊到计算机中去,这是汉字处理的关键;其次,汉字在计算机内如何表⽰和存储?如何与西⽂兼容?最
后,如何将汉字的处理结果从计算机内输出?
为此,必须将汉字代码化,即对汉字进⾏编码。对应于上述汉字处理过程中的输⼊、内部处理及输出这三
个主要环节,每⼀个汉字的编码都包括输⼊码、交换码、内部码和字形码。在计算机的汉字信息处理系统中,
处理汉字时要进⾏如下的代码转换:输⼊码→交换码→内部码→字形码。
(1)输⼊码: 作⽤是,利⽤它和现有的标准西⽂键盘结合来输⼊汉字。输⼊码也称为外码。主要归为四类:
a)数字编码:数字编码是⽤等长的数字串为汉字逐⼀编号,以这个编号作为汉字的输⼊码。例如,
unicode汉字区位码、电报码等都属于数字编码。
b)拼⾳码:拼⾳码是以汉字的读⾳为基础的输⼊办法。
c)字形码:字形码是以汉字的字形结构为基础的输⼊编码。例如,五笔字型码(王码)。
d)⾳形码:⾳形码是兼顾汉字的读⾳和字形的输⼊编码。
(2)交换码:⽤于汉字外码和内部码的交换。交换码的国家标准代号为GB2312-80。
(3)内部码:内部码是汉字在计算机内的基本表⽰形式,是计算机对汉字进⾏识别、存储、处理和传输
所⽤的
编码。内部码也是双字节编码,将国标码两个字节的最⾼位都置为"1",即转换成汉字的内部码。
(4)字形码:字形码是表⽰汉字字形信息(汉字的结构、形状、笔划等)的编码,⽤来实现计算机对汉字的输
出(显⽰、打印)。
2.VC中汉字的编码⽅式
vc/c++正是采⽤了GB2312内部码作为汉字的编码⽅式,因此vc/c++中的各种输⼊输出⽅法,如
vc/c++正是采⽤了GB2312内部码作为汉字的编码⽅式,因此vc/c++中的各种输⼊输出⽅法,如
cin/wcin,cout/wcout,scanf/wsanf,都是基于GB2312的,如果汉字的内码不是这种编码⽅式,那么利⽤上述各种⽅法就不会正确的解析汉字。
仔细观察ASCII字符表,从第161个字符开始,后⾯的字符并不经常为⽤户所使⽤,负值也未使⽤。
GB2312编码⽅式充分利⽤这⼀特性,将161-255(-95~-1)之间的数值空间作为汉字的标识码。既然
255-161 = 94不能满⾜汉字容量的要求,就将每两个字符并在⼀块(即⼀个汉字占两个字节),显然,94* 94
=8836基本上已经满⾜了常⽤汉字个数的要求。计算机处理字符时,当连续处理到两个⼤与160(或-95~-1)的字节时,就认为这两个字节存放了⼀个汉字字符。可以⽤下⾯的Demo程序来模拟vc/c++中输出汉字字符的过程。
unsigned char input[50];
cin>>input;
int flag=0;
for(int i =0 ;i < 50 ;i++)
{
if(input[i] > 0xa0 && input[i] != 0)
{
if(flag == 1)
{
cout<<"chinese character"<<endl;
flag = 0;
}
else
{
flag++;
}
}
else if(input[i] == 0)
{
break;
}
else
{
cout<<"english character"<<endl;
}
}
输⼊:Hello中国 (“中国”对应的GB2312内码为:214 208,185 250)
输出:english character
english character
english character
english character
english character
chinese character
chinese character
vc/c++中的英⽂字符仍然采⽤ASCII编码⽅式。可以设想,其他国家程序员利⽤vc/c++编写程序输⼊本国字符时,vc/c++则会采⽤该国的字符编码⽅式来处理这些字符。
问题⼜产⽣了,韩国的vc/c++程序在中国的vc/c++上运⾏时,如果没有相应的内码库,则对韩语字符的显⽰有可能出现乱码。我个⼈猜测,vc安装程序中应该带有不同国家的内码库,这样⼀来肯定会占⽤很⼤的空间。如果所有的国家使⽤统⼀的编码⽅式,且所有的程序设计语⾔和开发⼯具都⽀持这种编码⽅式该多好!⽽现实中,确实已经有这种编码⽅式了,且许多新的语⾔也都⽀持这种编码⽅式,如Java、C#等,它就是下⾯的Unicode编码
3.新的内码标准---Unicode
Unicode(统⼀码、万国码、单⼀码)是⼀种在计算机上使⽤的字符编码。它为每种语⾔中的每个字符设定了统⼀并且唯⼀的⼆进制编码,以满⾜跨语⾔、跨平台进⾏⽂本转换、处理的要求。1990年开始研
发,1994年正式公布。随着计算机⼯作能⼒的增强,Unicode也在⾯世以来的⼗多年⾥得到普及。最新版本的 Unicode 是 2005年3⽉31⽇推出的Unicode 4.1.0 。另外,5.0 Beta已于2005年12⽉12⽇推出,以供各会员评价。
Unicode 编码系统可分为编码⽅式和实现⽅式两个层次。
编码⽅式:Unicode 的编码⽅式与 ISO 10646 的通⽤字符集(Universal Character Set,UCS)概念相对应,⽬前的⽤于实⽤的 Unicode 版本对应于 UCS-2,使⽤16位的编码空间。也就是每个字符占⽤2个字节。这样理论上⼀共最多可以表⽰ 216 个字符。基本满⾜各种语⾔的使⽤。实际上⽬前版本的 Unicode 尚未
节。这样理论上⼀共最多可以表⽰ 216 个字符。基本满⾜各种语⾔的使⽤。实际上⽬前版本的 Unicode 尚未填充满这16位编码,保留了⼤量空间作为特殊使⽤或将来扩展。
实现⽅式:Unicode 的实现⽅式不同于编码⽅式。⼀个字符的 Unicode 编码是确定的。但是在实际传
输过程中,由于不同系统平台的设计不⼀定⼀致,以及出于节省空间的⽬的,对 Unicode 编码的实现⽅式有所不同。Unicode 的实现⽅式称为Unicode转换格式(Unicode Translation Format,简称为 UTF)。
如,UTF-8 编码,这是⼀种变长编码,它将基本7位ASCII字符仍⽤7位编码表⽰,占⽤⼀个字节(⾸位补0)。⽽遇到与其他 Unicode 字符混合的情况,将按⼀定算法转换,每个字符使⽤1-3个字节编码,并利⽤⾸位为0或1进⾏识别。
Java与C#语⾔都是采⽤Unicode编码⽅式,在这两种语⾔中定义⼀个字符,在内存中存放的就是这个字符的两字节Unicode码。如下所⽰:
char a='我'; => 内存中存放的Unicode码为:25105
4.内码的相互转换
(1)vc中的实现⽅法
利⽤Windows系统提供的API:::MultiByteToWideChar和::WideCharToMultiByte
::MultiByteToWideChar:实现当前码到Unicode码的转换;
::WideCharToMultiByte:实现Unicode码到当前码的转换;
(2)Java中的实现⽅法
String vcString=new Bytes("UTF-8"),"gb2312");
java的编码应该是UTF-8
(3)C#中的实现⽅法
四 vc中的MutiByte Charater Set 和 Wide Character Set
1.MultiByte Charater Set⽅式
这种⽅式以按字节为单位存放字符,即如果⼀个字符码为两字节,则在内存中占两字节,字符码为⼀字节,就占⼀字节。例如,字符串“中国abc”的编码为:中(0xd6、0xd0)、国(0xb9、0xfa)、a(0x61)、
b(0x62)、c(0x63)、/0(0x00),就存为如下⽅式:
对应的类型,⽅法有:
char、scanf、printf、cin、cout …
2.Wide Character Set
这种⽅式是以两字节为单位存放字符,即如果⼀个字符码为两字节,则在内存中占四字节,字符码为⼀字节,就占两字节。例如,字符串“中国abc”就存为如下⽅式:
对应的类型,⽅法有:
wchar_t、wscanf、wprintf、wcin、wcout …
造成上⾯存储⽅式的根本原因在于,wchar_t类型其实是⼀个unsigned short 类型。如,存储上⾯字符串的数组的定义为:wchar_t buffer[8] 等价于unsigned short buffer[8].⽽所有以字母w开头的⽅法也都是以unsigned short类型,即两字节为单位来处理字符,因此,存储在wchar_t类型数组中的字符串⽆法⽤cout显⽰,只能⽤wcout⽅法来显⽰。
由于Unicode码也是采⽤两个字节,因此Wide Character Set⽅式能够很好的⽀持Unicode码的存储,但是在vc的环境下要将⼀个Unicode码存⼊两字节⽽不是四字节内存中,必须通过上⾯的API函数
::MultiByteToWideChar。⾸先,将当前的编码转换为Unicode码,然后,将每个字符的Unicode码放⼊每⼀个wchar_t类型的变量中。以下是⼀个实例代码:
char input[50];
cin>>input;
int size;
size=::MultiByteToWideChar(CP_ACP,0,input,strlen(input)+1,NULL,0);
if(size==0)
return -1;
wchar_t*widebuff=new wchar_t[size];
::MultiByteToWideChar(CP_ACP,0,input,strlen(input)+1,widebuff,size);
输⼊:中国abc
Debug断点调试:
size==6
数组widebuff[0-size]占12字节,存放了6个字符的Unicode码,码值为:
中(0x4e2d) 国(0x56fd) a(0x0061) b(0x0062) c(0x0063) d(0x0000)
这时,数组的⼤⼩size等于输⼊的字符个数加上⼀个结束符,符合我们的想象。
五 引⼊问题的错误分析
(1) 没有理解编译器中的编码⽅式
虽然vc/c++中汉字的编码占两个字节,但并不是Unicode码,是GB2312码。
(2) 没有理解MutiByte Charater Set 和 Wide Character Set的存储原则;
在vc/c++中,“中国”按char[5]来对待,⽽wchar_t a[3]实际上是三个unsigned short类型的变量,因此赋值时会越界。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论