VC----实现汉字简繁转换

来源:互联网 发布:acfun看漫画软件 编辑:程序博客网 时间:2024/06/05 22:52

转载请注明出处:http://blog.csdn.net/yf210yf/article/details/7850472

繁体为什么分为乱码和非乱码的。现在总算搞清楚了
看起来是乱码那种叫Big5,非乱码的叫GBK繁体
GBK包括了简体和繁体
乱码的是Big5

GB2312字集是简体字集,全称为GB2312(80)字集,共包括国标简体汉字6763个。 
BIG5字集是台湾繁体字集,共包括国标繁体汉字13053个。 
GBK字集是简繁字集,包括了GB字集、BIG5字集和一些符号,共包括21003个字符。

一般来说,如果您在简体中文操作系统中使用繁体字,选GBK码繁体中文;如果您在繁体中文操
作系统中使用繁体字,选Big5码繁体中文。


不知道会不会写的很多,总之先补一下知识:

(1)计算机汉字编码简介

关于汉字编码

  为进行信息交换,各汉字使用地区都制订了一系列汉字字符集标准。

① GB2313字符集,收入汉字6763个,符号715个,总计7478个字符,这是大陆普遍使用的简体字符集。楷体-GB2313、仿宋-GB2313、华文行楷等市面上绝大多数字体持显示这个字符集,亦是大多数输入法所采用的字符集。市面上绝大多数所谓的繁体字体,其实采用的是GB-2313字符集简体字的编码,用字体显示为繁体字,而不是直GBK字符集中繁体字的编码,错误百出。

  ② BIG-5字符集,收入13060个繁体汉字,808个符号,总计13868个字符,目前普遍使用于台湾、香港等地区。台湾教育部标准宋体楷体等港台大多数字体支持这个字符集的显示。

  ③ GBK字符集,又称大字符集(GB=GuóBiāo国标,K=扩展),包含以上两种字符集汉字,收21003个汉字,882个符号,共计21885个字符,包括了中日韩(CJK)统一汉20902个、扩展A(CJK Ext-A) 中的汉字52个。Windows 95\98简体中文版就带有这个GBK.txt文件。宋体、隶书、黑体、幼圆、华文中宋、华文细黑、华文楷体、标楷(DFKai-SB)Arial Unicode MSMingLiUPMingLiU等字体支持显示这个字符集。微软拼音输入法2003、全拼、紫光拼音等输入法,能够录入如镕镕炁夬喆嚞姤赟赟龑昳堃慜靕臹等GBK简繁体汉字。


  BIG-5 (繁体中文)GB-2313 (简体中文),编码不相兼容,字符在不同的操作系统中便产生乱码。文本文字的简体与繁体(文字及编码)之间的转换,可用BabelPad
TextProConvertz之类的转码软件来解决。若是程序,Windows XP操作系统,可用Microsoft AppLocale Utility 1.0解决;Windows 2000的操作系统,大概只有用:中文之星、四通利方、南极星、金山快译之类的转码软件方能解决了。

  ④ GB18030字符集,包含GBK字符集、CJK Ext-A 全部6582个汉字,共计27533个汉字。宋体-18030、方正楷体(FZKai-Z03)、书同文楷体(MS Song)宋体(ht_cjk+)、香港华康标准宋(DFSongStd)、华康香港标准楷体、CERG Chinese Font、韩国New Gulim,以及微软Windows Vista操作系统提供的宋黑楷仿宋等字体亦支持这个字符集的显示。Windows 98支持这个字符集,以下的字符集则不支持。手写输入法逍遥笔4.0版支持GB18030字符集及方正超大字符集汉字的录入。


  ⑤ 方正超大字符集,包含GB18030字符集、CJK Ext-B中的36862个汉字,共计64395个汉字。宋体-方正超大字符集支持这个字符集的显示。Microsoft Office XP2003简体
中文版就自带有这个字体。Windows 2000的操作系统需安装超大字符集支持包Surrogate更新


  ⑥ ISO/IEC 10646 / Unicode字符集,这是全球可以共享的编码字符集,两者相互兼融,涵盖了世界上主要语文的字符,其中包括简繁体汉字,计有:CJK统一汉字20902
个,CJK Ext-A 6582个,Ext-B 42711个,共计70195个汉字。SimSun-ExtB(宋体)MingLiU-ExtB(细明体)能显示全部Ext-B汉字。至今尚无单独一款字体能够显示全部70195个汉字,但可用海峰五笔、新概念五笔、仓颉输入法世纪版、新版的微软新注音、仓颉输入法 6.0 (单码功能)等输入法录入。Ext-C还有2万多个汉字。

  关于Unicode
  由于各国国家标准字集所收的汉字字数、常用字的差异,虽然象中国两岸GB/BIG5字集常用字基本类似,转换后阅读并不成问题,但是这种编码转换的混乱关系,对文字交流始终是一种障碍。因此相关国家的标准化组织和文字工作者经过共同努力,终于在93年完成了包含中日韩(CJK)汉字的Unicode 汉字标准ISO 10646.1。 Unicode是完全双字节表示的多国文字编码体系,编码空间0x0000-0xFFFF
ISO 10646.1汉字标准使用编码0x4E00-9FA5,共包含20902个汉字。其中: 大陆(S)提出的汉字17124个,台湾(T)提出的汉字17258; ST的并集,即中国(C)提出的汉字为20158个。 日本(J)提出的汉字为12157个,中国未提出的690(Ja); 韩国(K)提出的汉字为7477个,其中中国未提出的90(Ka); JaKa并集共744字。 支持Unicode编码的相关电脑系统软件,如Unix, Win95已有推出,但是由于UnicodeASCII码是用双字节编码(即一般电脑系统中的单字节ASCII前加 0x00),同时其汉字编码与各国的现有编码也不兼容,造成现有的软件和数据不能直接使用,所以目前完全使用Unicode软件系统的用户并不多,大多数只将它此作为一个

国际语言编码标准来使用。


(2)基本原理

由上述编码知识可知,字体的切换其实就是编码的切换

GB2312<->Unicode<->BIG5

这样一个流程,Unicode充当切换的桥梁。


(3)VC的实现

先上代码再解释:

#include   <iostream> #include <atlstr.h>#include <locale.h>using   namespace   std; char* UnicodeToBIG5(const wchar_t* szUnicodeString);char* UnicodeToGB2312(const wchar_t* szUnicodeString);wchar_t* GB2312ToUnicode(const char* szGBString);char* GB2312ToBIG5(const char* szGBString);void   main() {         locale loc( "chs" );//定义“区域设置”为中文方式//wchar_t str[]=L"中国";char str[100];cin>>str;        char * rlt=GB2312ToBIG5(str);CString   cStr1; cStr1.Format( "%s",rlt); setlocale(LC_ALL, ".950");cout<<rlt<<endl;} wchar_t* GB2312ToUnicode(const char* szGBString){UINT nCodePage = 936; //GB2312int nLength=MultiByteToWideChar(nCodePage,0,szGBString,-1,NULL,0);wchar_t* pBuffer = new wchar_t[nLength+1];MultiByteToWideChar(nCodePage,0,szGBString,-1,pBuffer,nLength);pBuffer[nLength]=0;return pBuffer;}//BIG5 转换成 Unicode:wchar_t* BIG5ToUnicode(const char* szBIG5String){UINT nCodePage = 950; //BIG5int nLength=MultiByteToWideChar(nCodePage,0,szBIG5String,-1,NULL,0);wchar_t* pBuffer = new wchar_t[nLength+1];MultiByteToWideChar(nCodePage,0,szBIG5String,-1,pBuffer,nLength);pBuffer[nLength]=0;return pBuffer;}//Unicode 转换成 GB2312:char* UnicodeToGB2312(const wchar_t* szUnicodeString){UINT nCodePage = 936; //GB2312int nLength=WideCharToMultiByte(nCodePage,0,szUnicodeString,-1,NULL,0,NULL,NULL);char* pBuffer=new char[nLength+1];WideCharToMultiByte(nCodePage,0,szUnicodeString,-1,pBuffer,nLength,NULL,NULL);pBuffer[nLength]=0;return pBuffer;}//Unicode 转换成 BIG5:char* UnicodeToBIG5(const wchar_t* szUnicodeString){UINT nCodePage = 950; //BIG5int nLength=WideCharToMultiByte(nCodePage,0,szUnicodeString,-1,NULL,0,NULL,NULL);char* pBuffer=new char[nLength+1];WideCharToMultiByte(nCodePage,0,szUnicodeString,-1,pBuffer,nLength,NULL,NULL);pBuffer[nLength]=0;return pBuffer;}//繁体中文BIG5 转换成 简体中文 GB2312char* BIG5ToGB2312(const char* szBIG5String){LCID lcid = MAKELCID(MAKELANGID(LANG_CHINESE,SUBLANG_CHINESE_SIMPLIFIED),SORT_CHINESE_PRC);wchar_t* szUnicodeBuff = BIG5ToUnicode(szBIG5String);char* szGB2312Buff = UnicodeToGB2312(szUnicodeBuff);int nLength = LCMapString(lcid,LCMAP_SIMPLIFIED_CHINESE, (LPCSTR)szGB2312Buff,-1,NULL,0);char* pBuffer = new char[nLength + 1];LCMapString(0x0804,LCMAP_SIMPLIFIED_CHINESE,(LPCSTR)szGB2312Buff,-1,pBuffer,nLength);pBuffer[nLength] = 0;delete[] szUnicodeBuff;delete[] szGB2312Buff;return pBuffer;}//简体中文 GB2312 转换成 繁体中文BIG5char* GB2312ToBIG5(const char* szGBString){LCID lcid = MAKELCID(MAKELANGID(LANG_CHINESE,SUBLANG_CHINESE_SIMPLIFIED),SORT_CHINESE_PRC);int nLength = LCMapString(lcid,LCMAP_TRADITIONAL_CHINESE,szGBString,-1,NULL,0);char* pBuffer=new char[nLength+1];LCMapString(lcid,LCMAP_TRADITIONAL_CHINESE,szGBString,-1,pBuffer,nLength);pBuffer[nLength]=0;wchar_t* pUnicodeBuff = GB2312ToUnicode(pBuffer);char* pBIG5Buff = UnicodeToBIG5(pUnicodeBuff);delete[] pBuffer;delete[] pUnicodeBuff;return pBIG5Buff;}

运行的效果图:

输入:简体中文

c输出:繁体中文


转载请注明出处:http://blog.csdn.net/yf210yf/article/details/7850472

(4)详解

假如您是高手,请跳过,下面的讲解可能对您很基础。

1>locale loc( "chs" );//定义“区域设置”为中文方式

2>wchar_t定义的是宽字节

所谓的多字节与宽字节,就是指ASCII字符和Unicode字符。前者占一个字节,后者占两个字节。
Win2000以后的系统从底层支持Unicode字符。就现在来看,尽量要要用Unicode字符,这样可以提高程序效率,避免系统在内部进行转换。Win2000以后的系统中,所有API函
数只接受Unicode字符,如果传入ASCII字符,系统会自动把它转换成Unicode字符,再调用函数。

例如:

‘中’   Unicode码值:U+4E2D  UTF-8 编码 e4 b8 ad
‘文’   Unicode码值:U+6587  UTF-8 编码  e6 96 87

我们需要理解用char[ ]和wchar_t [ ]来存放“中文”时有什么不同

    char    str[]="中文";
    wchar_t wstr[] 
= L"中文";    

我们使用gdb这个强大的工具来查看str[]和wst[]中究竟都存放了哪些值(请注意颜色之间的对应关系)

(gdb) x /8xb &str
0xbf83decd:     0xe4    0xb8    0xad    0xe6    0x96    0x87    0x00    0xf0
(gdb) x 
/12xb &wstr
   0xbf83dec0:     0x2d    0x4e    0x00    0x00    0x87    0x65    0x00    0x00
   0xbf83dec8:     0x00    0x00    0x00    0x00

不难看出,char str[ ]中存储的是“中文"的UTF-8编码,这是因为我的机器的locale是zh_CN.UTF-8,程序源文件的自然采用的是UTF-8编码,因此编译器 在处理 char str[ ]="中文"; 时,t它对str[]所做得初始化实际上可以理解成    char str[ ]={ 0xe4,0xb8,0xad,0xe6,0x96,0x87,0x00}

而wchar_t wstr[ ]中存放的是“中文"的Unicode码值,这符合C标准对宽字符的定义。这里需要解释的是C标准中规定宽字符是16 bit的字符,而从GNU glibc 2.2开始,类型wchar_t只用于存放32-bit的ISO 10646码值(你可以粗略的把ISO 10646理解成Unicode,尽管它们并不是一回事),而独立于当前使用的locale;因此在上面的输出中,我们看到每个Unicode码值用 32bit表示,而不是16bit。
参考:http://blog.csdn.net/lovekatherine/article/details/1868724

而要正常打印宽字节,需要

setlocale (LC_ALL,"");wchar_t wstr[] = L"中文";    wcout<<wstr<<endl;

注意setlocale (LC_ALL,"");很重要,否则会输出??

那关于setlocale的介绍如下

setlocale

配置地域化信息。

语法:   char * setlocale ( int category, const char * locale );

返回值: 字符串

函数种类: 操作系统与环境

内容说明

本函数用来配置地域的信息,设置当前程序使用的本地化信息。参数 category 有下列的选择:

    * LC_ALL 包括下面的全项选项都要。
    * LC_COLLATE 配置字符串比较,PHP 目前尚未实作出来本项。
    * LC_CTYPE 配置字符类别及转换。例如全变大写 strtoupper()。
    * LC_MONETARY 配置金融货币,PHP 目前尚未实作。
    * LC_NUMERIC 配置小数点后的位数。
    * LC_TIME 配置时间日期格式,与 strftime() 合用。

而参数 locale 若是空字符串 "",则会使用系统环境变量的 locale 。若 locale 为零(NULL),则不会改变地域化配置,返回当前的地域值,若系统尚未实作则返回 false。

Locales contain information on how to interpret and perform certain input/output and transformation operations taking into consideration location and language specific settings.

Most running environments have certain locale information set according to the user preferences or localization. But, independently of this system locale, on start, all C programs have the "C" locale set, which is a rather neutral locale with minimal locale information that allows the result of programs to be predictable. In order to use the default locale set in the environment, this function can be called with "" as the locale parameter.

The locale set on start is the same as setlocale(LC_ALL,"C") would set.
The entire default locale can be set by calling setlocale(LC_ALL,"");

C程序开始的时候的设置和 setlocale(LC_ALL,"C")相同

使用系统默认的设置调用setlocale(LC_ALL,"");

The parts of the current locale affected by a call to this function are specified by parameter category.
Return Value
On success, A pointer to a C string identifying the locale currently set for the category. If category is LC_ALL and different parts of the locale are set to different values, the string returned gives this information in a format which may vary between compiler implementations.

例子:

/* setlocale example */#include <stdio.h>#include <time.h>#include <locale.h>int main (){  time_t rawtime;  struct tm * timeinfo;  char buffer [80];  struct lconv * lc;  time ( &rawtime );  timeinfo = localtime ( &rawtime );  int twice=0;  do {    printf ("Locale is: %s/n", setlocale(LC_ALL,NULL) ); //使用NULL参数,获取当前配置    strftime (buffer,80,"%c",timeinfo);    printf ("Date is: %s/n",buffer);    lc = localeconv ();    printf ("Currency symbol is: %s/n-/n",lc->currency_symbol);    setlocale (LC_ALL,"");  } while (!twice++);    return 0;}One of the possible outputs when the previous code is run is:Locale is: CDate is: 01/15/07 13:33:47Currecy symbol is: -Locale is: English_United States.1252Date is: 1/15/07 1:33:47 PMCurrency symbol is: $

3)

CString   cStr1; 

cStr1.Format( "%s",rlt); 

用到了CString 和 char *的转换

CString   转换成char*: char*   ch   =   cstring.GetBuffer(cstring.GetLength()); char*转换成CString: CString.Format( "%s ",ch); 

4>在这几个函数中还涉及一个问题

char* UnicodeToBIG5(const wchar_t* szUnicodeString);
char* UnicodeToGB2312(const wchar_t* szUnicodeString);
wchar_t* GB2312ToUnicode(const char* szGBString);
char* GB2312ToBIG5(const char* szGBString);

const char*, char const*, char*const的区别

char * const cp     : 定义一个指向字符的指针常数,即const指针
const char* p       : 定义一个指向字符常数的指针
char const* p       : 等同于const char* p

5>MultiByteToWideChar 接口
字面意思可以看出是多字节转宽字节
//Big5 -> Unicode
//用MultiByteToWideChar来返回字符个数
lngLen = MultiByteToWideChar(950, 0, strSource, -1, NULL, 0) 'MultiByteToWideChar 返回的是字符个数,乘 2 才是所需要分配的空间
lngLen = lngLen - 1 'MultiByteToWideChar 返回的个数多了1

strUnicode = String(lngLen * 2, 0)
lngRet = MultiByteToWideChar(950, 0, strSource, -1, strUnicode, lngLen)

//Unicode -> GB 繁体
lngLen = WideCharToMultiByte(936, 0, strUnicode, -1, NULL, 0, NULL, 0)
//lngLen = Len(strUnicode)
strGBKT = String(lngLen, 0)lngLen = WideCharToMultiByte(936, 0, strUnicode, -1, strGBKT, lngLen, NULL, 0)
思路是先
先用MultiByteToWideChar来返回字符个数
然后转换成新的字符编码
转载请注明出处:http://blog.csdn.net/yf210yf/article/details/7850472


原创粉丝点击