关于Windows系统下编程之字符处理

                 关于Windows系统下编程之字符处理

我们在 widows下编程时,经常遇到关于字符串的处理的问题,特别是在用 VC编程时,我们经常犯错误,所以我结合我的编程经验和我学习 widows核心编程这本书后的体会,来自己作一个总结。
1、字符集
在我们平时的编代码的过程中,总在不但地处理各种关于字符集的问题。对于我们来说,习惯于将文本串作为一系列单字节字符串来处理,并且在结尾加上 ”/0”,它用来标识串的结束。当我们调用 strlen(…)函数时, 它在以 0 结尾的单字节字符数组中返回字符的数目。
2、单字节与双字节字符集
一个字节占用 8(bit)。而双字节字符集中,字符串中的每个字符在编码时可以包含一个字节或包含两个字节(这时 strlen(…)函数就不能告诉我们字符串中究竟有多少个字符,它只能告诉我们在该字符串中的第一个 ”/0”之前有多少个字节。在 VC中,我们可以用 _mbslen(…)来代替。)。
3Unicode字符集

Unicode字符集提供了简单而有一致的表示字符串的方法,它规定字符串中每一个字符编码都是16(两个字节)。所以利用Unicode字符集可以编码216 = 65535个字符。这样,它就能够对世界各国的书面文字中的所有字符进行编码,远远超过了单字节字符集的2 5 6 个字符的数目。                       

  部分 Unicode 区域字符表
1 6 位代码
字符
16 位代码
字符
0 0 0 0 - 0 0 7 F
A S C I I
0 3 0 0 - 0 3 6 F
通用区分标志

0 0 8 0 - 0 0 F F

拉丁文 1 字符

0 4 0 0 - 0 4 F F

西里尔字母
0 1 0 0 - 0 1 7 F
欧洲拉丁文
0 5 3 0 - 0 5 8 F
亚美尼亚文

0 1 8 0 - 0 1 F F

扩充拉丁文

0 5 9 0 - 0 5 F F

西伯莱文

0 2 5 0 - 0 2 A F

标准拼音

0 6 0 0 - 0 6 F F

阿拉伯文

0 2 B 0 - 0 2 F F

修改型字母
0 9 0 0 - 0 9 7 F
梵文
 
4windowsUnicode
我们基本上天天和 Windows打交道,知道Windows 2000/XP是用Unicode进行开发的。在Windows 2000/XP中用于创建窗口、呈现文本、进行字符串操作等所有核心函数都需要Unicode字符串。在平时我们 调用任何一个 Windows 函数并给它传递一个ANSI字符串,那么系统首先要将字符串转换成 Unicode ,然后将 Unicode 字符串传递给操作系统。如果希望函数返回ANSI字符串,系统就会首先将 Unicode 字符串转换成ANSI字符串,然后将结果返回给你的应用程序。所有这些转换操作都是在你看不见的情况下发生的。当然,进行这些字符串的转换需要占用系统的时间和内存。
例如,如果调用 CreateWindowEx函数,并传递类名字和窗口标题文本的非 Unicode字符串,那么 CreateWindowEx必须分配内存块(在你的进程的默认堆中),将非 Unicode字符串转换成 Unicode字符串,并将结果存储在分配到的内存块中,然后调用 Unicode版本的 CreateWindowEx函数。 对于用字符串填入缓存的函数来说,系统必须首先将 Unicode 字符串转换成非 Unicode 字符串,然后你的应用程序才能处理该字符串。由于系统必须执行所有这些转换操作,因此你的应用程序需要更多的内存,并且运行的速度比较慢。通过从头开始用 Unicode 来开发应用程序,就能够使你的应用程序更加有效地运行
5 、编写 Unicode 源代码
C 运行期库对 Unicode 的支持
为了利用 Unicode 字符串,定义了一些数据类型,如我们熟悉的 wchar_t

typedef unsigned short wchar_t

egwchar_t szBuffer[100] ;//在内存中的大小为100*18bit = 200 byte。可以存储最多为9 9 个字符的Unicode字符串和一个结尾为零的字符

 
现在一些标准的 ANSI C 字符串处理函数都有相应的等价的 Unicode 函数。如:
eg:char * strcat(char *,const char *);
char_t * wcscat(wchar_t *,const wchar_t *)
标准的ANSI C 字符串函数和它们的等价Unicode函数
char * strchr(const char *,int);
wchar_t * wcschr(const wchar_t *,wchar_t);
 
int strcmp(const char *,const char *);
int wcscmp(const wchar_t *,const wchar_t *);
 
char * strcpy(char *,const char *);
wchar_t * wcscpy(wchar_t *,const wchar_t *);
 
size_t strlen(const char *);
size_t wcslen(const wchar_t *);
注意:所有的Unicode 函数均是以wcs 开头,而ANSI 函数则以str 开头
 
Tchar,h头文件
Tchar.h 文件的唯一作用是帮助创建ANSI/Unicode通用源代码文件。它包含你应该用在源代码中的一组宏,而不应该直接调用str函数或者wcs函数。如果在编译源代码文件时定义了UNICODE,这些宏就会引用wcs这组函数。如果没有定义_UNICODE,那么这些宏将引用str这组宏。

A WCHAR if UNICODE is defined, a CHAR otherwise

#ifdef UNICODE
typedef WCHAR TCHAR;
#else typedef char TCHAR;
#endif
所以根据上面的定义我们可以将TCHAR看为通用的字符类型。
eg : TCHAR szBuffer[100];
     TCHAR ch = “Hello”;

注意:TCHAR ch = “Hello”这行代码在Visual C++中,如果没有定义_UNICODE,编译是按ANSI编码,可以通过(在VC中默认是ANSI编码)。但当我们定义了_UNICODE时,编译就通不过,我们必须改成TCHAR ch = L“Hello”。字符串(literal string )前面的大写字母L ,用于告诉编译器该字符串应该作为Unicode字符串来编译。当编译器将字符串置于程序的数据部分中时,它在每个字符之间分散插入零字节。这种变更带来的问题是,现在只有当定义了_UNICODE时,程序才能成功地进行编译。我们需要另一个宏,以便有选择地在字符串的前面加上大写字母L 。这项工作由_TEXT宏来完成,_TEXT宏也在T C h a r. h 文件中做了定义。

如果定义了 _UNICODE ,那么 _TEXT 定义为下面的形式:
#define_TEXT(x)    __T(x)
#define__T(x)      L## x
如果没有定义 _UNICODE ,那么 _TEXT 定义为下面的形式:

#define _TEXT(x) x

所以使用该宏,可以改写上面这行代码为TCHAR ch = _TEXT(“Hello”),这样,无论是否定义了_UNICODE宏,它都能够正确地进行编译。

Windows定义的Unicode数据(This type is declared in WinNT.h)

Typedef wchar_t WCHAR; //16-bit Unicode Characters

Typedef WCHAR *PWSTR;//Pointer to a new null-terminated //string of 16-bitUnicode characters

Typedef CONST WCHAR *PCWSTR;//Pointer to a constant //null-terminated string of //16-bit Unicode characters

A PWSTR if UNICODE is defined, a PSTR otherwise

#ifdef UNICODE

 typedef LPWSTR PTSTR;

#else

typedef LPSTR PTSTR;

#endif
 

A PCWSTR if UNICODE is defined, a PCSTR otherwise.

#ifdef UNICODE
typedef LPCWSTR PCTSTR;
#else
typedef LPCSTR PCTSTR;
#endif
windows 中的 Unicode 函数和 ANSI 函数
前面我说过,在 Windows 中有好多的函数有两个版本,一个接受 Unicode 字符串,一个接受 ANSI 串,如:
#ifdefUNICODE
#defineCreateWindowEx CreateWindowExW
#else
#define CreateWindowEx CreateWindowExA
#endif  // !UNICODE
当编译源代码模块时, UNICOD是否已经作了定义,将决定你调用的是哪个 CreateWindowEx版本。当转用一个 1 6 位的 Windows应用程序时,你在编译期间可能没有定义 UNICODE。对 CreateWindowEx函数的任何调用都会将该宏扩展为对 CreateWindowExA的调用,即对 CreateWindowExA N S I 版本的调用。由于 1 6 Wi n d o w s 只提供了 C r e a t e Wi n d o w s E x A N S I 版本,因此可以比较容易地转用它的应用程序。如果定义了 UNICODE,则是对 CreateWindowExW调用。
Unicode ANSI 之间转换字符串
MultiByteToWideChar(…) 用于将多字节字符串转换成宽字节字符串
int MultiByteToWideChar (
UINT CodePage , // 标识一个与多字节字符串相关的代码页号
DWORD dwFlags , // Flags indicating the conversion type
LPCSTR lpMultiByteStr , // 要转换的字符串指针
int cbMultiByte , // 用与指明源串的长度 ( 以字节计算 ), 如果传值为 -1 // 那么函数返回源串的长度 ; 0 ,则失败
LPWSTR lpWideCharStr ,// 目标串的地址
int cchWideChar // 目标串的长度 ( 以自己计算 ), 如果传值为 0 ,则函数不 // 执行转换,而是返回使转换成功所需要的缓存的值 .
);
WideCharToMultiByte )用于将宽字节字符串转换成等价的多字节字符串
int WideCharToMultiByte(
UINT CodePage ,
DWORD dwFlags ,
LPCWSTR lpWideCharStr ,
int cchWideChar ,
lpMultiByteStr ,
int cbMultiByte ,
LPCSTR lpDefaultChar ,
LPBOOL lpUsedDefaultChar );
由于和 MultiByteToWideChar(…) 差不多,所以可以对比着看 MSDN
 
有错误欢迎大家指正,请发邮件到 [email protected]

你可能感兴趣的:(关于Windows系统下编程之字符处理)