Windows核心编程 字符和字符串处理

1.尽量在程序中使用unicode字符串
2.使用新函数来避免缓冲区溢出和其他问题
函数有W,A版时,A会先将传入的字符转换为Unicode,再调用W版,再将结果转换为ANSI;
C运行库中的函数是自力更生的;
3.wchat_t,是一个16位的Unicode字符,声明Unicode字符和字符串的方法如下:(L用于通知编译器该字符应该编译为一个Unicode字符)
   
   
wchar_t c=L'A';//a 16bit character
wchar_t szBuffer[100]= L"A String";//99个16位的字符和一个16位的结束0
   
   
#ifdef _UNICODE
typedefwchar_t TCHAR;// 定义了_UNICODE宏的情况下,TCHAR是两个字节的字符
#define __T(x) L##x
// ##是ANSI C标准的预处理语法,它叫做“粘贴运算符”,即将前面的L与宏参数合在一起。
#define _T(x) __T(x)// _T(x)一个下划线的变成__T(x)两个下划线的
#else
#define __T(x) x // 未定义_UNICODE宏的情况下,TCHAR是一个字节的字符
typedefchar TCHAR;// 非宽字符的字符串常量
#endif
   
   
#ifdef UNICODE
typedef WCHAR TCHAR,*PTCHAR ,*PTSTR;
typedef CONST WCHAR *PCTSTR;
#define __TEXT(quote) L##quote
#else
typedef CHAR TCHAR ,*PTCHAR,PTSTR;
typedef CONST CHAR *PTCHAR;
#define __TEXT(quote) quote
#endif
#define TEXT(quote) __TEXT(quote)
3.C运行库中的安全字符串函数
Microsoft的StrSafe.h中定义了新的安全字符串函数(string.h包含在其中), 将StrSafe.h放在最后!
eg: 
  
  
PTSTR _tcscpy(PTSTR strDestination,PCTSTR strSource);
erron_t _tcscpy_s(PTSTR strDestination,size_tnumberOfCharacters,PCTSTR strSource);
当失败时,返回错误号,字符串被截断为一个空字符串,同时会终止程序运行
   
   
#include<stdlib.h>//包含_countof宏获取字符数
#include<cstdio>
#include<StrSafe.h>
usingnamespace std;
 
int main()
{
wchar_t buffer[5]= L"1234";
wcscpy_s(buffer,_countof(buffer), L"12345");
return0;
}
4.获取更多控制
C运行库新增了一些函数用于在执行字符串处理时提供更多控制。
   
   
MicrosoftStrSafe.h文件中定义新的安全字符串函数,除了新的安全字符串函数,还新增了一些函数,用于在执行字符串处理时提供更多的控制。可以控制填充符,或者指定如何进行截断
 
下面为部分原型:常用的
 
HRESULT StringCchCat( PTSTR pszDest,size_t cchDest, PCTSTR pszSrc);
 
HRESULT StringCchCatEx( PTSTR pszDest,size_t cchDest, PCTSTR pszSrc,
 
PTSTR*ppszDestEnd,size_t*pcchRemaining, DWORD dwFlags );
 
还有StringCchCpy
 
StringCchCpyEx
 
StringCchPrintf
 
StringCchPrintfEx
 
可以看出含有“Cch”,这表示count of characters即字符数,通常用_countof宏来获取。
 
还有含有“Cb”,如StringCbCat(Ex),StringCbCopy(Ex),StringCbPrintf(Ex)这些函数指定的是字节数,
 
通常使用sizeof操作符来获取此值
 
这些函数都返回HRESULT不同于安全函数(带_S后缀的),当缓冲区太小的时候,这些函数会执行截断
5. windows字符串函数

windows也提供了各种字符串处理函数。

例如我们经常比较字符串以进行相等性测试或是排序,为此,最理想的函数是

CompareString(Ex)注意返回值。。(0失败,1小于,2等于,3大于,一般将返回值-2再判断)

CompareStringOrdinal(注:只支持unicode

第一个函数功能大用法比较复杂,对于这两个函数的用法,请见MSDN

6.推荐的字符和字符串处理方式

1、开始讲文本字符串想象为字符数组,而不是char会字节的数组!

2、用通用的数据类型(如TCHAR、PTSTR、LPTSTR)来表示文本字符和字符串!

3、用明确的数据类型(如BYTE和PBYTE)来表示字节和字节指针和数据缓冲区!

4、用TEXT或_T宏表示字面字符和字符串,但是为了保持一致性,避免两者混用,虽然两者是一样的!

5、执行全集替换(例如用PTSTR替换为PSTR)

6、注意在字符串有关计算的地方。如:某函数形参为缓冲区字符数   那么应该用_countof取得如果要用malloc来分配空间,那么需要的是字节数,应该用sizeof取得!!最好定义一个宏来避免这个问题:#define chmalloc( nCharacters )  (TCHAR*)malloc( nCharacters * sizeof( TCHAR) ) 

7、避免使用printf系列函数,尤其不要用%s和%S字段类型来进行ANSI和unicode字符串之间的相互转换。应该用 MultiByteToWideCharWideCharToMultiByte进行函数。

8、UNICODE 和_UNICODE符号要么同时制定要么都不要指定要使用新的安全函数 和 新增的字符串函数(更多控制力的) 和 windows的字符串处理函数

10、利用RTC编译器标志来自动检测缓冲区溢出

11、对于字符串的比较  如果是比较字符串(路径、文件名、XML元素以及注册表等)应该用CompareStringOrdinal函数 ,速度更快而如果想其他的用户字符串,一般需要显示在用户界面上应该需要用CompareString(Ex)因为它在比较的时候需要考虑用户的区域设置,灵活性好,在世界的任何一个地方,任意一种语言,只要设置了其区域设置,就能很好的处理和现实。

 7.Unicode与ASIN转换

intMultiByteToWideChar(

  UINT CodePage, 
    DWORD dwFlags,
    LPCSTR lpMultiByteStr,
int cchMultiByte, //为-1时自动判断大小
    LPWSTR lpWideCharStr,
int cchWideChar //为0时,该函数返回目标缓存区需要的大小
  );
intWideCharToMultiByte(
    UINT CodePage,
    DWORD dwFlags,
    LPWSTR lpWideCharStr,
int cchWideChar, //为-1时自动判断大小
    LPCSTR lpMultiByteStr,
int cchMultiByte, //为0时,该函数返回目标缓存区需要的大小
    LPCSTR lpDefaultChar, //遇到一个不能转换的宽字符,函数便会使用pDefaultChar参数指向的字符
    PBOOL pfUsedDefaultChar  //至少有一个字符不能转换为其多字节形式,函数就会把这个变量设为TRUE)
  );

CodePage :指定执行转换的 代码页 ,这个参数可以为系统已安装或有效的任何代码页所给定的值。你也可以指定其为下面的任意一值:
CP_ACP:ANSI 代码页 ;CP_MACCP:Macintosh代码页;CP_OEMCP:OEM代码页;
CP_SYMBOL:符号 代码页 (42);CP_THREAD_ACP:当前线程ANSI代码页;
CP_UTF7:使用UTF-7转换;CP_UTF8:使用UTF-8转换。
 eg:
   
   
1. ANSI to Unicode
wstring ANSIToUnicode(const string& str )
{
int len =0;
len = str.length();
int unicodeLen =::MultiByteToWideChar( CP_ACP,
0,
str.c_str(),
-1,
NULL,
0);
wchar_t* pUnicode;
pUnicode =newwchar_t[unicodeLen+1];
memset(pUnicode,0,(unicodeLen+1)*sizeof(wchar_t));
::MultiByteToWideChar( CP_ACP,
0,
str.c_str(),
-1,
(LPWSTR)pUnicode,
unicodeLen );
wstring rt;
rt =(wchar_t*)pUnicode;
delete pUnicode;
return rt;
}
2.Unicode to ANSI
string UnicodeToANSI(const wstring& str )
{
char* pElementText;
int iTextLen;
// wide char to multi char
iTextLen =WideCharToMultiByte( CP_ACP,
0,
str.c_str(),
-1,
NULL,
0,
NULL,
NULL );
pElementText =newchar[iTextLen +1];
memset((void*)pElementText,0,sizeof(char)*( iTextLen +1));
::WideCharToMultiByte( CP_ACP,
0,
str.c_str(),
-1,
pElementText,
iTextLen,
NULL,
NULL );
string strText;
strText = pElementText;
delete[] pElementText;
return strText;
}
3. UTF-8 to Unicode
wstring UTF8ToUnicode(const string& str )
{
int len =0;
len = str.length();
int unicodeLen =::MultiByteToWideChar( CP_UTF8,
0,
str.c_str(),
-1,
NULL,
0);
wchar_t* pUnicode;
pUnicode =newwchar_t[unicodeLen+1];
memset(pUnicode,0,(unicodeLen+1)*sizeof(wchar_t));
::MultiByteToWideChar( CP_UTF8,
0,
str.c_str(),
-1,
(LPWSTR)pUnicode,
unicodeLen );
wstring rt;
rt =(wchar_t*)pUnicode;
delete pUnicode;
return rt;
}
4.Unicode to UTF-8
string UnicodeToUTF8(const wstring& str )
{
char* pElementText;
int iTextLen;
// wide char to multi char
iTextLen =WideCharToMultiByte( CP_UTF8,
0,
str.c_str(),
-1,
NULL,
0,
NULL,
NULL );
pElementText =newchar[iTextLen +1];
memset((void*)pElementText,0,sizeof(char)*( iTextLen +1));
::WideCharToMultiByte( CP_UTF8,
0,
str.c_str(),
-1,
pElementText,
iTextLen,
NULL,
NULL );
string strText;
strText = pElementText;
delete[] pElementText;
return strText;
}
 8.判断是否Unicode还是ASIN
使用IsTextUnicode()不一定正确
   
   
IsTextUnicode编辑
本词条缺少信息栏、名片图,补充相关内容使词条更完整,还能快速升级,赶紧来编辑吧!
IsTextUnicode函数
确定一个缓冲区是否可能包含Unicode文本。
语法
BOOL IsTextUnicode(
  __in const VOID *lpv,
  __in int iSize,
  __inout LPINT lpiResult
);
参数
lpv
指向要检查的输入缓冲区。
iSize
lpv指向的缓冲区大小,以字节为单位。
lpiResult
可选
返回值
如果缓冲区的数据通过了指定测试,返回非零值。如果缓冲区的数据没有通过指定测试该函数返回0

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值