现在的位置: 首页 > 综合 > 正文

宽字符跟ASCII——区别及测试

2013年07月08日 ⁄ 综合 ⁄ 共 5238字 ⁄ 字号 评论关闭

一.宽字符介绍

首先说,什么是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之间的转换。

看这段代码.

+ expand sourceview 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多字节编码有大体认识了吧。

 

 

 

Unicode

Unicode is a method of software character encoding that treats all characters as having a fixed width of two bytes. This method is used as an alternative to Microsoft® Windows® ANSI character encoding, which because it represents characters in one byte, is limited to 256 characters. Because Unicode can represent over 65,000 characters, it accommodates many languages whose characters are not represented in ANSI encoding.

Unicode does not require the use of code pages, which ANSI uses to accommodate a limited set of languages. Unicode is an improvement upon the Double-Byte Character Set (DBCS), which uses a mixture of 8-bit and 16-bit characters and still requires code pages. For more information about the Unicode standard, see http://www.unicode.org.

The ODBC 3.5 (or higher) Driver Manager is Unicode-enabled. This affects two major areas: function calls and string data types. The Driver Manager maps function string arguments and string data as required by the application and driver, both of which can be either Unicode-enabled or ANSI-enabled. These two areas are discussed in detail in the sections, Unicode Function Arguments and Unicode Data.

The ODBC 3.5 (or higher) Driver Manager supports the use of a Unicode driver with both a Unicode application and an ANSI application. It also supports the use of an ANSI driver with an ANSI application. The Driver Manager provides limited Unicode-to-ANSI mapping for a Unicode application working with an ANSI driver.

This section contains the following topics.

 

 

delphi帮助文档关于这方面的叙述!

抱歉!评论已关闭.