C++主要使用的是C-Style字符串,而M$在Windows中又增加了很多C-Style字符串的变体。这个一多嘛,就容易乱~
所谓字符串,就是由字符组合而成,所以我们先来讲讲字符类型。
首先,存在两种最基本的字符类型:char和wchar_t。char大家都很熟悉了,我就跳过。至于wchar_t,是应用于UNICODE的宽字符,即一个字符2Bytes,16Bits。事实上,Windows中利用
typedef unsigned short wchar_t
定义wchar_t
然后为了书写方便(MS我也没觉得有多大差别),M$又把那两个基本字符类型重新的给他typedef了一遍,即:
typedef char CHAR
typedef wchar_t WCHAR
为了使得兼容性更加,M$又定义了TCHAR数据类型:
#ifdef UNIOCDE
typedef WCHAR TCHAR
#else
typedef CHAR TCHAR
#end if
这样,你不用关心是要使用ANSI字符串还是Unicode,编译器会自动根据你的OS来选择。
————————————————————————————————————————————————————————————
————————————————————————————————————————————————————————————
然后,M$又利用上面的几种基本数据类型,定义了一些字符串指针类型。
LPSTR和LPCSTR:LPSTR是指向以0结尾的ANSI字符串的指针,后者是const指针
typedef CHAR* LPSTR
typedef const CHAR* LPCSTR
LPWSTR和LPCWSTR:LPWSTR是指向以0结尾的UNICODE字符串的指针,后者是const指针
typedef WCHAR* LPWSTR
typedef const WCHAR* LPCWSTR
同样,为了摆脱对ANSI还是UNICODE的选择麻烦,M$也增加了LPTSTR和LPCTSTR两个字符串指针类型。他们被如下定义:
typedef TCHAR* LPTSTR
#ifdef UNICODE
typedef LPSTR LPTSTR
#else
typedef LPWSTR LPTSTR
#endif
/
typedef const TCHAR* LPCTSTR
#ifdef UNICODE
typedef LPCSTR LPCTSTR
#else
typedef LPCWSTR LPCTSTR
#endif
ps:你会在某些地方看到存在PSTR/PWSTR/PTSTR等等,与上面的只却一个L的字符串指针类型。实际上,这个是长指针和短指针问题。LPXX是长指针,PXX是短指针。不过在32Bit的系统上,二者已经没有区别。
然后说说两个比较成熟好用的字符串类型:String和CString
String是C++的标准字符串,需要string(不带.h)头文件和std名字空间支持。
CString是M$为MFC设计的字符串,功能更加强大,而且这玩意儿是安全的。需要atlstr.h文件和MFC DLL的支持。不过目前已经有人将此类型从MFC中分离~
为了增强程序的通用性,还必须注意以下几点:
1、既然程序里不能出现char,那表示字符串时,就不能再习惯性的用char*了。应该改为TCHAR*,或者是PTSTR。后一种是 windows的变量,类似的有:PSTR、PTSTR、LPTSTR、LPSTR、PCTSTR等等等等。这也是让人一开始接触会头大的地方。其实并非如此恐怖,我以PCTSTR为例做个解释:P代表指针(和LP是一个东西,LP的本意是Long Pointer,16位windows时代的遗留物。),C代表const,T代表TCHAR,STR代表字符串。所以PCTSTR其实就是const TCHAR* 的意思。而PSTR也就是char* 的意思。所以我们在表示字符串时也不能使用PSTR等不带T的变量类型名。
2、表示字符串常量时,不能简单的用双引号括起来,因为那代表ascii字符串。同样也不能在前面加L,因为那代表unicode。我们的程序要做到的是通用性,即不是ascii也不是unicode。所以我们在字符串前应该加的是TEXT,比如MessageBox(NULL,TEXT("Fypher"),TEXT("FF"),MB_OK)。TEXT还可用于字符。比如TCHAR m=TEXT('A');
3、TCHAR FF[50]。FF能装多少字符?哈!不要习惯性的sizeof(FF)了,应该_countof(FF)或者sizeof(FF)/sizeof(TCHAR)。因为我们不确定TCHAR到底是char 还是 wchar_t。
4、该和一堆老朋友说再见了……我们不能再使用以前的字符串处理函数或者字符处理函数了。比如strlen、strcat、strcmp等等等等……因为这些是ascii专用的,通通改成使用T家族的吧。前缀都换成_tcs。比如_tcslen、_tcscat、_tcscmp等等……顺便补充一下wcs前缀是wchar_t使用的。恩,还有大家用得超爽的sprintf,今后就改成_stprintf了吧~呵呵。补充:swprintf是 wchar_t它家的。对了,windows认为_tcscpy、_tcscat等不安全,所以使用这些函数编译器会报警。可以改用windows推出的 _tcscpy_s、_tcscat_s等“安全”函数,其实就是多了个参数用来指明缓冲区大小(记得用_countof哦~!^_^)。windows 还推出了形如StringCchCat的一套字符串处理函数,我没怎么用过。windows也有一个字符串比较函数CompareString。功能比 _tcscmp强大多了。比如可以设置忽略大小写等。
5、IsTextUnicode函数可以用过一系列统计学的方法判断某个字符串是不是unicode字符串。 MultiByteToWideChar和WideCharToMultiByte函数可实现Ascii和Unicode字符串的相互转化。这些的使用场合都不大。因为我们的程序应该做到“没有”ascii和unicode。
6、恩,虽然绝大多数情况下应该使用TCHAR,但是记住GetProcAdress这个特殊的函数吧,它的参数只能是char*。因为在导出函数表里函数名是用ascii码写的……
7、最后一点,记得要#include
8、注意:str前缀与wcs前缀都是标准C函数,需要有标准C运行库才能够使用。而lstr前缀的是window提供的原生函数,不需标准C运行库。
(转自:http://www.cnblogs.com/cchyao/archive/2010/09/16/1827793.html)
补充:
1)ASCII字符串和宽字符串
在应用程序中使用两种字符:一是char型字符串,负责记录ANSI字符集,它是指向一个char数组的指针,每个char型变量大小是一个字节,字符串是以0标志字符串结束的;一是wchar_t型的宽字符串,负责描述unicode字符集,它是指向一个wchar_t数组的指针,wchar_t字符大小为两个字节,字符串以0标志字符串结束。
ANSI字符构造如下:
char *str1 = "ASCE";
UNICODE字符构造如下:
wchar_t *str2 = L"ASCE";
(注:在构造字符串时使用关键字“L”,编译器会自动生成所需要的宽字符)
在驱动开发中,DDK将char和wchar_t替换成CHAR和WCHAR。