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

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

2015-04-27 16:11 405 查看
1.尽量在程序中使用unicode字符串

2.使用新函数来避免缓冲区溢出和其他问题

函数有W,A版时,A会先将传入的字符转换为Unicode,再调用W版,再将结果转换为ANSI;

C运行库中的函数是自力更生的;

3.wchat_t,是一个16位的Unicode字符,声明Unicode字符和字符串的方法如下:(L用于通知编译器该字符应该编译为一个Unicode字符)

wchar_tc=L'A';//a16bitcharacter
wchar_tszBuffer[100]=L"AString";//99个16位的字符和一个16位的结束0


#ifdef_UNICODE
typedefwchar_tTCHAR;//定义了_UNICODE宏的情况下,TCHAR是两个字节的字符
#define__T(x)L##x
//##是ANSIC标准的预处理语法,它叫做“粘贴运算符”,即将前面的L与宏参数合在一起。
#define_T(x)__T(x)//_T(x)一个下划线的变成__T(x)两个下划线的
#else
#define__T(x)x//未定义_UNICODE宏的情况下,TCHAR是一个字节的字符
typedefcharTCHAR;//非宽字符的字符串常量
#endif


#ifdefUNICODE
typedefWCHARTCHAR,*PTCHAR,*PTSTR;
typedefCONSTWCHAR*PCTSTR;
#define__TEXT(quote)L##quote
#else
typedefCHARTCHAR,*PTCHAR,PTSTR;
typedefCONSTCHAR*PTCHAR;
#define__TEXT(quote)quote
#endif
#defineTEXT(quote)__TEXT(quote)


3.C运行库中的安全字符串函数

Microsoft的StrSafe.h中定义了新的安全字符串函数(string.h包含在其中),将StrSafe.h放在最后!

eg:

PTSTR_tcscpy(PTSTRstrDestination,PCTSTRstrSource);
erron_t_tcscpy_s(PTSTRstrDestination,size_tnumberOfCharacters,PCTSTRstrSource);


当失败时,返回错误号,字符串被截断为一个空字符串,同时会终止程序运行

#include<stdlib.h>//包含_countof宏获取字符数
#include<cstdio>
#include<StrSafe.h>
usingnamespacestd;
intmain()
{
wchar_tbuffer[5]=L"1234";
	wcscpy_s(buffer,_countof(buffer),L"12345");
return0;
}


4.获取更多控制

C运行库新增了一些函数用于在执行字符串处理时提供更多控制。

在Microsoft的StrSafe.h文件中定义新的安全字符串函数,除了新的安全字符串函数,还新增了一些函数,用于在执行字符串处理时提供更多的控制。可以控制填充符,或者指定如何进行截断
下面为部分原型:常用的
HRESULTStringCchCat(PTSTRpszDest,size_tcchDest,PCTSTRpszSrc);
HRESULTStringCchCatEx(PTSTRpszDest,size_tcchDest,PCTSTRpszSrc,
PTSTR*ppszDestEnd,size_t*pcchRemaining,DWORDdwFlags);
还有StringCchCpy
StringCchCpyEx
StringCchPrintf
StringCchPrintfEx等
可以看出含有“Cch”,这表示countofcharacters即字符数,通常用_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取得!!最好定义一个宏来避免这个问题:#definechmalloc(
nCharacters)(TCHAR*)malloc(
nCharacters*sizeof(TCHAR))

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

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

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

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

intMultiByteToWideChar(

  UINTCodePage,
    DWORDdwFlags,
    LPCSTRlpMultiByteStr,
intcchMultiByte,//为-1时自动判断大小
    LPWSTRlpWideCharStr,
intcchWideChar//为0时,该函数返回目标缓存区需要的大小
  );
intWideCharToMultiByte(
    UINTCodePage,
    DWORDdwFlags,
    LPWSTRlpWideCharStr,
intcchWideChar,//为-1时自动判断大小
    LPCSTRlpMultiByteStr,
intcchMultiByte,//为0时,该函数返回目标缓存区需要的大小
    LPCSTRlpDefaultChar,//遇到一个不能转换的宽字符,函数便会使用pDefaultChar参数指向的字符
    PBOOLpfUsedDefaultChar//至少有一个字符不能转换为其多字节形式,函数就会把这个变量设为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.ANSItoUnicode
wstringANSIToUnicode(conststring&str)
{
intlen=0;
len=str.length();
intunicodeLen=::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);
wstringrt;
rt=(wchar_t*)pUnicode;
deletepUnicode;
returnrt;
}
2.UnicodetoANSI
stringUnicodeToANSI(constwstring&str)
{
char*pElementText;
intiTextLen;
//widechartomultichar
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);
stringstrText;
strText=pElementText;
delete[]pElementText;
returnstrText;
}
3.UTF-8toUnicode
wstringUTF8ToUnicode(conststring&str)
{
intlen=0;
len=str.length();
intunicodeLen=::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);
wstringrt;
rt=(wchar_t*)pUnicode;
deletepUnicode;
returnrt;
}
4.UnicodetoUTF-8
stringUnicodeToUTF8(constwstring&str)
{
char*pElementText;
intiTextLen;
//widechartomultichar
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);
stringstrText;
strText=pElementText;
delete[]pElementText;
returnstrText;
}[/code]

8.判断是否Unicode还是ASIN

使用IsTextUnicode()不一定正确

IsTextUnicode编辑
本词条缺少信息栏、名片图,补充相关内容使词条更完整,还能快速升级,赶紧来编辑吧!
IsTextUnicode函数
确定一个缓冲区是否可能包含Unicode文本。
语法
BOOLIsTextUnicode(
  __inconstVOID*lpv,
  __inintiSize,
  __inoutLPINTlpiResult
);
参数
lpv
指向要检查的输入缓冲区。
iSize
由lpv指向的缓冲区大小,以字节为单位。
lpiResult
可选
返回值
如果缓冲区的数据通过了指定测试,返回非零值。如果缓冲区的数据没有通过指定测试该函数返回0。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: