您的位置:首页 > 编程语言

window核心编程学习笔记 (一) 错误处理以及Unicode

2015-07-27 22:13 363 查看

一、window错误处理机制

每一次我们调用windows函数时,windows都会先验证我们传给它的参数,然后再开始执行任务。如果传入的参数无效,或者由于其他原因导致操作无法执行,则函数的返回值将指出函数因为某些原因失败了。通常情况下,如果Windows函数能返回错误代码,将有助于我们理解函数调用为什么会失败。Microsoft编辑了一个列表,其中列出了所有可能的错误代码,并为每个错误代码分配了一个32位的编号。我们可以使用GetLastError函数查看具体是什么错误。
但是注意GetLastError必须在windows函数失败之后立马调用,因为调用另一个windows函数,此值可能被改写。成功调用的windows函可能用ERROR_SUCCESS改写此值。
在Microsoft visual studio 中,Microsoft的调试器支持一个很有用的功能-我们可以配置Watch(监视)窗口,让它始终显示该线程的上一个错误代码和错误文本描述。具体做法是:在Watch窗口中选择一行然后输入$err,hr.如图所示


此外VS 还提供了一个小工具Error Lookup, 利用他可以将错误代码转换为相应的文本描述符。假如你自己写的程序中检测到一个错误,又希望向用户显示错误的文本描述,而不是一个错误编码。那么我们可以用windows提供的FormatMessage。关于此函数的具体用法可以参考下面的博客:http://blog.csdn.net/harbinzju/article/details/6197839

假如我们要写一个供其他人调用的函数,这个函数可能会因为这样或者那样的原因失败,所以需要向调用者指出错误,因此我们可以设置线程的上一个错误代码,然后令自己函数返回false,设置上一个错误代码的函数为:
VOID SetLastError(DWORD dwErrCode);

二、字符和字符串处理

2.1字符编码

为了支持windows多语言与本地化引入了Unicode.我们知道C语言用char数据类型来表示一个8位ANSI字符。默认情况下在源代码声明一个字符串时,C编译器会把字符串中的字符转换成由8位char数据类型构成一个数组,而Microsoft的c/c++编译器定义了一个内建的数据类型wchar_t,它表示一个16位的Unicode字符。

2.2windows中的Unicode函数和Ansi函数

自Windows NT起,Windows的所有版本都完全用Unicode来构建。也就是说所有核心函数都需要Unicode字符串。假如你在调用windows函数时传入一个ANSI字符串,那么该函数说先会将ANSI字符串转换成Unicode然后才传给操作系统,如果该函数返回一个ANSI字符串,则会将Unicode转换程ANSI。当然,为了执行这些字符串的转换会产生系统必要的开销,所以作为一个windows程序员,我们应该尽量使用Unicode字符串。

2.3 初识新的安全字符串函数

假如您应用程序中包含StrSafe.h时,String.h也会被包含进来。C运行库中现有的字符串数处理函数(如_tcscpy)

已被标记为废弃不用。如果使用了这些函数,编译时就会发出警告。注意必须在包含所有文件之后才包含StrSafe.h

.建议利用编译器警告来明确地用安全版本来替换废弃不用的所有函数。

现有的每一个函数(如_tcscpy or _tcscat),都有一个对应的新版本函数。前面的名称相同但最后添加一个_s代表后缀。

erro_t _tcscpy_s(PTSTR dest,size_t numberOfChar,PCTSTR source);

erro_t _tcscat_s(PTSTR dest,size_t numberOfChar,PCTSTR source);

通过对缓冲区使用_countof宏我们可以很快计算出该buf的大小

Windows也提供了各种字符串处理函数。如果想要详细了解可以查看 ShlwApi.h,下面介绍2个字符串比较函数:

1、CompareString和CompareStringOrdinal详细用法可以查看MSDN

2.3 Unicode 与 ANSI 字符串之间的转换

我们在windows下写程序不免的会碰到Unicode与ANSI之间的转换,如下的windows函数可以实现转换功能:

( 1 ) ANSI -> Unicode

一般我们讲一个多字节转换成一个Unicode字符串可以按照如下步骤

(1)调用 MultiByteToWideChar,为 pWideCharStr 参数传入 NULL, 为cchWideChar 参数传入 0,为 cbMultiByte 参数传入 -1 。

(2)分配一块足以容纳转换后的 Unicode 字符串的内容。它的大小是上一个 MultiByteToWideChar 调用的返回值乘以 sizeof(wchar_t) 。

(3)再次调用MultiByteToWideChar,这一次将缓冲区地址作为 pWideCharStr 参数的值传入,将第一次 MultiByteToWideChar 调用的返回值乘以 sizeof(wchar_t) 后得到大小作为 cchWideChar 参数的值传入。

(4)使用转换后的字符串

(5)释放 Unicode 字符串占用的内存块。

但是这视乎不是个好方法,因为我们总是默认Unicode buffer应该是已经创建出来的,我们需要功能就相当于_tcscpy_s的功能,因此可以自己写一个函数进行封装这些步骤:

void ansi_to_unicode(CONST CHAR* pByte,TCHAR * pWideByte)

{

UINT nLengthOfWideByte = MultiByteToWideChar(CP_ACP,0,pByte,\

strlen(pByte)+1,NULL,0); // 特别注意返回值已经包含终止字符串0

MultiByteToWideChar(CP_ACP,0,pByte,strlen(pByte)+1,pWideByte,nLengthOfWideByte );

}

封装的函数如下:

void unicode_to_ansi(CONST TCHAR* pWideByte, CHAR * pByte)

{

UINT nlengthOfByte = WideCharToMultiByte(CP_ACP, 0, pWideByte, _tcslen(pWideByte) + 1, NULL, 0, NULL, NULL);

WideCharToMultiByte(CP_ACP, 0, pWideByte, _tcslen(pWideByte) + 1, pByte, nlengthOfByte, NULL, NULL);

}

但是在WideCharToMultiByte函数的使用中我向利用最后一个参数来判断是否又一个宽字符不能转换成byte的时候,出现莫名的错误,希望有一些大侠看到能给我一些提示。报错的代码如下:

bool unicode_to_ansi(CONST TCHAR* pWideByte, CHAR * pByte)

{
bool bRet = FALSE;

UINT nlengthOfByte = WideCharToMultiByte(CP_ACP, 0, pWideByte, _tcslen(pWideByte) + 1, NULL, 0, NULL, NULL);

WideCharToMultiByte(CP_ACP, 0, pWideByte, _tcslen(pWideByte) + 1, pByte, nlengthOfByte, NULL,(LPBOOL)& bRet );
return !bRet;

}


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: