第二章 Unicode简介(1)

来源:互联网 发布:旋转木马js效果带左右 编辑:程序博客网 时间:2024/04/28 14:42

        在标准C中,通过一种叫“宽字符”的概念来支持用多个字节代表一个字符的字符集。多字节字符集主要影响C语言运行库函数。宽字符并不一定是Unicode。Unicode只是宽字符编码的一种实现。我们进在Windows中,将宽字符和Unicode作为同义词。

更宽的字符

        使用Unicode或者是宽字符并不会改变C语言中的字符数据类型。C语言中的宽字符是基于wchar_t数据类型的。这个数据类型被定义在多个头文件中。包括WCHAR.H,如下所示:

typedef    unsigned     short    wchar_t;

可以用下面的语句来定义一个包含单个宽字符的变量:

wchar_t    c = 'A'; 

也可以在单个字符串常量前面使用L前缀,如下所示,以表明它们应被解释为宽字符:

wchar_t    c = L'A';

但这通常是不需要的,C编译器总是会在字符后面加0的。

还可以如下定义一个已初始化的指向宽字符串的指针:

wchar_t    *p = L"Hello!";

宽字符的库函数

宽字符版本的strlen函数被称为wcslen,并定义在STRING.H和WCHAR.H中,strlen函数的声明如下:

size_t    __cdecl  strlen( const char *);

而wcslen函数的声明如下:

size_t    __cdecl    wcslen( const wchar_t *);

在使用宽字符的时候,字符串的字符长度并没有改变,改变的只是字节长度。

维护一个源代码文件

维护一个单一源代码文件,使之可以编译成ASCII或Unicde。其中一个方法是使用包含在VC中的TCHAR.H头文件。这个头文件并不是ANSI C标准的一部分,所以其中定义的每一个函数和宏都有一个下划线前缀。TCHAR.H为那些需要字符串参数的普通运行库函数(例如,_tprintf和_tcslen)提供了一系列的替代名称。这些函数有时被称为“通用”的函数名字,因为它们可以指定Unicode或非Unicode版本的函数。

如下定义,其中那一堆数字符号被称为“令牌粘贴”,它使得字母L和红参数拼接在一起。

#ifdef _UNICODE

typedef    wchar_t  TCHAR;

#define    _tcslen    wcslen

#define    __T(x)    L##x

#else

typedef    char      TCHAR;

#defin    _tcslen    strlen

#define    __T(x)    x

#endif

#define    _T(x)    __T(x)

#define    _TEXT(x)    __T(x)

Windows头文件的类型

Windows程序包含着WINDOWS.H头文件,该文件又包含着许多其他头文件,例如WINDEF.H,该文件中又有许多在Windows中使用的基本数据类型的定义,同时它本身也包含WINNT.H。WINNT.H则负责处理基本的Unicde支持功能。

        WINNT.H在一开始就包含C的头文件CTYPE.H,而着是C的众多头文件之一,包含着wchar_t 的定义。WINNT.H定义了两个新的被称作CHAR和WCAHR的数据类型:

typedef    char    CHAR;

typedef    wcahr_t    WCHAR;      //wc是匈牙利标记法,用来说明这是一个宽字符。

CHAR和WCHAR是写Windows程序时推荐使用的数据类型,它们分别用于定义8位或者16位的字符。WINNT.H将TCHAR定义为一个通用的字符类型。如果标识符UNICODE(没有下划线)被定义了,则TCHAR 和指向TCHAR的指针就被定义为WCHAR和指向WCHAR的指针;如果标识符UNICODE没有被定义,则TCHAR和指向TCHAR的指针就分别被定义为char和指向char的指针。WINNT.H头文件还定义了一个宏,它将L添加到一个字符串的第一个引号前。定义如下:

#ifdef    UNICODE

typedef    WCHAR    TCHAR ,    *  PTCHAR;

#define    __TEXT(quote)    L##quote

#else

typedef    char    TCHAR ,     *  PTCHAR;

#define    __TEXT(quote)    quote

#endif

#define    TEXT(quote)    __TEXT(quote)

Windows函数调用

如果需要在程序中混合调用并匹配ASCII和宽字符函数,则可以明确使用MessageBoxA和MessageBoxW函数。但我们可以继续使用MessageBox。根据是否已定义UNICODE标识符,MessageBox将实际调用MessageBoxA或是MessageBoxW。如下所示:

#ifdef    UNICODE

#define    MessageBox    MessageBoxW

#else

#define    MessageBox    MessageBoxA

#endif

Windows的字符串函数

Microsoft  C包含宽字符以及通用版的需要字符串参数的C语言运行库函数。不过,Windows复制了其中一部分C函数。例如,下面是Windows定义的一组字符串函数,这些函数用来计算字符串长度、复制字符串、链接字符串和比较字符串:

ILength  =  lstrlen( pString );

pString  =  lstrcpy( pString1,  pString2 );

pString  =  lstrcpyn( pString1,  pString2,  iCount );

pString  =  lstrcat( pString1,  pString2 );

iComp  = lstrcmp( pString1,pString2 );

iComp  = lstrcmpi( pString1,pString2 );

这些函数提供了与C运行库中对应的函数功能。当定义了UNICODE标识符时,这些函数就接受宽字符串,否则只接受宽字符串。

在Windows中使用printf

Windows中不存在标准输入和标准输出的概念,所以我们可以在Windows程序中使用fprintf 函数,但不能使用printf 函数。sprintf 函数定义如下:

int sprintf ( char * szBuffer,  const  char * szFormat, ... );

第一个参数是一个字符串缓冲区;后面是一个格式字符串。使用sprintf 时,除了要考虑格式字符串与被格式化的变量不合外,还要考虑定义的字符串缓冲区必须足够大以存放结果。Microsoft 的专用函数 _snprintf 解决了这一问题,此函数引入一个参数来指定字符缓冲区的大小。

当需要对可变参数执行像printf 一样的格式化时,可以用vsprintf 来实现我们自己的函数。vsprintf只有三个参数,第三个参数是指向待格式化的参数数组的指针。

当然,随着宽字符的引入,sprintf系列的函数增加了许多,使得函数名让人困惑。下表列出了Microsoft版的C语言运行库和Windows所支持的所有Sprintf类函数。

  ASCII 宽字符 通用 可变数目的参数       标准版 sprintf swprintf _stprintf 最大长度版 _snprintf _snwprintf _sntprintf Windows版 wsprintfA wsprintfW wsprintf 参数数组的指针       标准版 vsprintf vswprintf _vstprintf 最大长度版 _vsnprintf _vsnwprintf _vsntprintf Windows版 wvsprintfA wvsprintfW wvprintf

 其中最大长度版(_sntprintf和_vsntprintf)声明在TCHAR.H头文件中

—————————————————————     我是快乐的分割线    —————————————————————

包含在windows.h头文件中

类型与宏:

TCHAR    pString;

TEXT(pString);

如果有定义UNICODE,则以上定义为宽字符,否则为普通的但字节字符

函数总结:

iLength  =  lstrlen( pString );         //计算字符串长度

pString  =  lstrcpy( pString1,  pString2 );         //复制字符串

pString  =  lstrcpyn( pString1,  pString2,  iCount );        //复制字符串

pString  =  lstrcat( pString1,  pString2 );        //链接字符串

iComp  = lstrcmp( pString1,pString2 );        //比较字符串

iComp  = lstrcmpi( pString1,pString2 );        //比较字符串

iLength = wsprintf( szBuffer,"The sum of %i and %i is %i",5,3,5+3 );     //字符串格式化函数

iLength = wvsprintf( szBuffer,  szFormat, pArgList );     //字符串格式化函数(参数数组的指针)

 

原创粉丝点击