Windows核心编程 第二章 字符和字符串处理

1. Windows Vista中每个Unicode字符都是用UTF-16编码。

 

2. Unicode 0x7F个字符兼容ASCII编码。

 

UTF-8 :将一些字符编码为1个字节,一些字符编码为2个字节,一些字符编码为3个字节,一些字符编码为4个字节。

UTF-16 :将每个字符编码为2个字节(16)

UTF-32  :将每个字符都编码为4个字节, 较少用, 一般在应用程序内部使用。

 

3. C语言中的字符表示:

char : 8位 ASCII 编码

wchar_t : 16位 Unicode (UTF-16)编码

 

4. 使用UTF-16字符串的时候应在字符串前面加上大写字母L。表明使用一个unicode字符串。

 

5. Windows编程中 源代码使用的数据类型应坚持使用Windows数据类型,增加代码的可读性。

 

6. Windows中提供两个编码版本的函数。以W结尾的是UNICODE编码函数,以A结尾的是ANSI编码的函数

如:

CreateWindowExW

CreateWindowExA

 

7. Windows内部使用的是UNICODE函数,因此开发时应该尽量使用Unicode 函数以提高应用程序的效率,避免Windows在内部还要将ANSI 函数转为UNICODE函数。

 

8. MSC库的ANSIUnicode版本之间没有互相调用关系的,没有编码转换开销。 

 

9. 宽字符函数:_tcscpy_tcscat_tcslen

 

10. UNICODE宏是Windows  API使用的,而MSC库中,对于非标准的东西用_前缀区分,所以_UNICODE宏是MSCRT库函数所使用。  使用C\C++编程中,要确保要么UNICODE 和 _UNICODEdefine或是全部没define

 

11. 使用StrSafe.h里面的安全字符处理函数。StrSafe库中提供 Cch和 Cb两种函数, Cch传入的是字符数,可用_countof取得,Cb表示的是字符串的字节数。 在源串过短时,<StrSafe.h>的函数处理方式是截断而<TChar.h>的函数则使用断言。

 

12.  自定义C运行库函数传入参数无效的异常处理方法:

(1) 定义一个 InvalidParameterHandler 函数,用于注册异常抛出函数。格式如下:

void InvalidParameterHandler(PCTSTR expression,

PCTSTR function,

PCTSTR file,

unsigned int line,

uintptr_t);

(2) 调用_set_invalid_parameter_handler 注册异常函数

(3) 使用_CrtSetReportMode 关系VS自带的debug dialog 。

 示例代码:

 1 /****************************************************************************************
 2 *    自定义C运行库函数传入参数无效的异常处理方法:                                                *
 3 *    (1) 定义一个 InvalidParameterHandler 函数,用于注册异常抛出函数。格式如下:                *
 4 *        void InvalidParameterHandler(PCTSTR expression,                                    *
 5 *            PCTSTR function,                                                            *
 6 *            PCTSTR file,                                                                *
 7 *            unsigned int line,                                                            *
 8 *            uintptr_t);                                                                    *
 9 *    (2) 调用_set_invalid_parameter_handler 注册异常函数                                    *
10 *    (3) 使用_CrtSetReportMode 关系VS自带的debug dialog 。                                    *
11 *****************************************************************************************/
12 
13 #include <cstdio>
14 #include <cstdlib>
15 #include <iostream>
16 #include <crtdbg.h>
17 #include <tchar.h>
18 #include <windows.h>
19 #include <strsafe.h>
20 using namespace std;
21 
22 void InvalidParameterHandler(PCTSTR expression, PCTSTR function, PCTSTR file, unsigned int line, uintptr_t )
23 {
24     wcout << "自定义的C运行库异常处理 : " << endl;
25     wcout << expression << endl;        //哪句表达式发生异常
26     wcout << function << endl;            //哪一个函数发生异常
27     wcout << file << endl;                //在哪个文件发生异常
28     wcout << line << endl;                //第几行抛出异常
29     throw 0;    //抛出异常
30 }
31 
32 int main (void)
33 {
34     _CrtSetReportMode(_CRT_ASSERT, 0);
35     _set_invalid_parameter_handler(InvalidParameterHandler);
36 
37     try{
38 
39         TCHAR szbefore[5] = L"BBBB";
40         TCHAR szAfter[5] = L"AAAA";
41         TCHAR buf[10] = {0};
42         errno_t ret = _tcscpy_s(buf, _countof(buf), L"0123456789");
43     }
44     catch(int err)
45     {
46         if ( 0 == err )
47             cout << "接受到 InvalidParameterHandler 抛出的异常!" << endl;
48     }
49 
50 
51     return 0;
52 }

13. 使用Shlwapi.h的字符串处理函数, 如:需要比较向用户显示字符串的比较函数使用 CompareString , 比较程序内部使用的字符串(如路径名、注册表项/值等)应使用CompareStringOrdinal

 

14. 使用MultiByteToWideChar 和 WideCharToMultiByte 可以转换字符编码。其中,在宽字节转多字节的时候,如果有Unicode字符在多字节编码中没有对应项,那宽字节会被替换成参数lpDefaultChar,并且lpUsedDefaultChar 会被标记为TRUE。当用这两个函数计算结果串的大小时,返回的是字符数。

 

15. IsTextUnicode 可以检测字符编码是属于UNICODE还是ASCII

 

16.关闭VS对不安全的字符串函数警告或报错的方法: 在源程序最顶端加上宏定义 #define _CRT_SECURE_NO_DEPRECATE  即可关闭字符串不安全函数的警告或报错。

 

Unicode 和 ANSI 编码相互转换示例代码:

#include <windows.h>
#include <iostream>
using namespace std;

// Unicode编码转为ASCII 编码
int UnicodeToAnsi(wchar_t *str_wide, char *str_ansi, unsigned int cbsize)
{
	return WideCharToMultiByte(CP_ACP, 0, str_wide, -1, str_ansi, cbsize, NULL, NULL);
}

// ASCII转为Unicode 编码
int AnsiToUnicode (char *str_ansi, wchar_t *str_wide, unsigned int chcount)
{
	return MultiByteToWideChar(CP_ACP, 0, str_ansi, -1, str_wide, chcount);
}

int main (void)
{
	// code conversion
	char str[50] = {0};
	wchar_t wide[] = L"人生长恨水厂东";

	cout << UnicodeToAnsi(wide, str, 50) << endl;
	cout << str << endl;


	char ansi[] = "人生长恨水厂东" ;
	wchar_t p[50];

	AnsiToUnicode(ansi, p, _countof(p));
	MessageBox(NULL, p, p, 0);

	return 0;
}

 

 

posted @ 2013-05-12 21:46  左懒  阅读(574)  评论(0编辑  收藏  举报