宽字符(wide char)

来源:互联网 发布:淘宝生意参谋在哪里看 编辑:程序博客网 时间:2024/03/29 13:44

From: http://blog.csdn.net/hairetz/archive/2009/05/18/4198191.aspx

一.宽字符介绍

首先说,什么是ASCII,ASCII是用来表示英文字符的一种编码规范。每个ASCII字符占用1个字节,因此,ASCII编码可以表示的最大字符数是255(00H—FFH)。

其实,英文字符并没有那么多,一般只用前128个(00H—7FH,最高位为0),其中包括了控制字符、数字、大小写字母和其它一些符号。而最高位为1的另128个字符(80H—FFH)被称为“扩展ASCII”,一般用来存放英文的制表符、部分音标字符等等的一些其它符号。

也就是说char a_char[]="Hello";

这里的a_char的每个字符占一个字节,也就是8bit的空间,当然,由于是C风格字符串,末尾还有'/0',sizeof的结果为6字节。这就是ASCII编码。

char a_char[]="你好hi";

这个时候cout<<sizeof(a_char)<<endl;结果是7,也就是会所每个汉字占2个字节,而每个英文字符只占一个字节,并且有一个'/0'结尾,这就是ASCII编码。

那什么是宽字符呢?那得先看什么是Unicode.

Unicode也是一种字符编码方法,它占用两个字节(0000H—FFFFH),容纳65536个字符,这完全可以容纳全世界所有语言文字的编码。
在Unicode里,所有的字符被一视同仁,汉字不再使用“两个扩展ASCII”,而是使用“1个Unicode”,也就是说,所有的文字都按一个字符来处理,它们都有一个唯一的Unicode码。

下面例举几个字符的编码以简单演示ANSI和Unicode的区别:

字符               A            N          和
ANSII码        41H         4eH     cdbaH
Unicode码   0041H    004eH   548cH

看完我上面所说的,相信这里的编码你不难理解了。

什么是宽字符:对宽字符的支持其实是ANSI C标准的一部分,用以支持多字节表示一个字符。宽字符和Unicode并不完全等同,Unicode只是宽字符的一种编码方式。

1、宽字符的定义

  在ANSI中,一个字符(char)的长度为一个字节(Byte)。使用Unicode时,一个字符占据一个字,C++在wchar.h头文件中定义了最基本的宽字符类型wchar_t:

typedef unsigned short wchar_t;
从这里我们可以清楚地看到,所谓的宽字符就是无符号短整数。

2.宽字符的使用

     这个很简单,wchar_t *str1=L" 你好Hello";
     这个L非常重要,只有带上它,编译器才知道你要将字符串存成一个字符一个字。还要注意,在L和字符串之间不能有空格。

3、宽字符串库函数

为了操作宽字符串,C++专门定义了一套函数,比如求宽字符串长度的函数是

size_t __cdel wchlen(const wchar_t*);
  为什么要专门定义这些函数呢?最根本的原因是,ANSI下的字符串都是以’/0’来标识字符串尾的(Unicode字符串以“/0/0”结束),许多字符串函数的正确操作均是以此为基础进行。而我们知道,在宽字符的情况下,一个字符在内存中要占据一个字的空间,这就会使操作ANSI字符的字符串函数无法正确操作。以”Hello”字符串为例,在宽字符下,它的五个字符是:
0x0048 0x0065 0x006c 0x006c 0x006f
在内存中,实际的排列是:

48 00 65 00 6c 00 6c 00 6f 00
  于是,ANSI字符串函数,如strlen,在碰到第一个48后的00时,就会认为字符串到尾了,用strlen对宽字符串求长度的结果就永远会是1!

  

二.宽字符与ASCII的转换

比较多的是用Windows的API,MultiByteToWideChar 跟WideCharToMultiByte 来实现宽字符跟ASCII之间的转换。

看这段代码.

view plaincopy to clipboardprint?
#include<windows.h>  
#include <iostream>  
 
using namespace std;  
 
int main()  
{  
      wchar_t wText[] = {L"宽字符转换实例!OK!"};  
      int i;  
      cout<<sizeof(wText)<<endl;     //宽字符占的字节数,24字节  
           DWORD dwNum = WideCharToMultiByte(CP_OEMCP,NULL,wText,-1,NULL,0,NULL,FALSE);  //获取宽字符数组wText转为ASCII需要的字节  
  cout<<dwNum<<endl;            //dwNum 长度为19字节  
  char *psText;  
  psText = new char[dwNum];         
  WideCharToMultiByte (CP_OEMCP,NULL,wText,-1,psText,dwNum,NULL,FALSE);     //把宽字符转为ASCII,写入psText 开始的内存  
  cout<<psText<<endl;  
  delete []psText;  
        return 0;  

#include<windows.h>
#include <iostream>

using namespace std;

int main()
{
   wchar_t wText[] = {L"宽字符转换实例!OK!"};
   int i;
   cout<<sizeof(wText)<<endl;     //宽字符占的字节数,24字节
           DWORD dwNum = WideCharToMultiByte(CP_OEMCP,NULL,wText,-1,NULL,0,NULL,FALSE);  //获取宽字符数组wText转为ASCII需要的字节
  cout<<dwNum<<endl;            //dwNum 长度为19字节
  char *psText;
  psText = new char[dwNum];      
  WideCharToMultiByte (CP_OEMCP,NULL,wText,-1,psText,dwNum,NULL,FALSE);     //把宽字符转为ASCII,写入psText 开始的内存
  cout<<psText<<endl;
  delete []psText;
  return 0;
}

  

上面这段代码可以实现从宽字符转为ASCII字符。

+ expand sourceview plaincopy to clipboardprint?
#include<windows.h>  
#include <iostream>  
 
using namespace std;  
 
int main()  
{  
      char sText[] = {"多字节字符串!OK!"};  
      cout<<sizeof(sText)<<endl;     //ASCII字符占用17字节,包括'/0'  
        DWORD dwNum = MultiByteToWideChar (CP_ACP, 0, sText, -1, NULL, 0);    
        cout<<dwNum<<endl;    //转换该ASCII字符串需要宽字符个数为11,'/0'也被转为宽字符  
        wchar_t *pwText;  
        pwText = new wchar_t[dwNum];  
        MultiByteToWideChar (CP_ACP, 0, sText, -1, pwText, dwNum);           //进行转换  
                     setlocale(LC_ALL,   "");    //因为要输出宽字符,设置一下  
        wcout<<pwText<<endl;   //输出宽字符,注意要用wcout  
        delete []pwText;  
        return 0;  

#include<windows.h>
#include <iostream>

using namespace std;

int main()
{
   char sText[] = {"多字节字符串!OK!"};
   cout<<sizeof(sText)<<endl;     //ASCII字符占用17字节,包括'/0'
  DWORD dwNum = MultiByteToWideChar (CP_ACP, 0, sText, -1, NULL, 0); 
  cout<<dwNum<<endl;    //转换该ASCII字符串需要宽字符个数为11,'/0'也被转为宽字符
  wchar_t *pwText;
  pwText = new wchar_t[dwNum];
  MultiByteToWideChar (CP_ACP, 0, sText, -1, pwText, dwNum);           //进行转换
                     setlocale(LC_ALL,   "");    //因为要输出宽字符,设置一下
  wcout<<pwText<<endl;   //输出宽字符,注意要用wcout
  delete []pwText;
  return 0;
}

 


上面这段代码可以实现从ASCII字符转为宽字符。

至此,大家应该对宽字符Unicode跟ASCII多字节编码有大体认识了吧。

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/hairetz/archive/2009/05/18/4198191.aspx