MFC中的乱起八糟----字符编码:LPTSTR,LPCTSTR, TCHAR等

 

注意,编写有 Unicode 意识的代码总是一件好事,比如:
CString graycat = CString(_T("Gray")) + _T("Cat");
这将使得你的代码可以直接移植。
 

1, 将参数从"const char *"转换为"LPCTSTR"

1 使用_T、L、TEXT等转换宏
2 MyFunZipCp(_T("C:\\SY.txt"),_T("C:\\SY.ZIP"),false);
3 或者
4 MyFunZipCp(L"C:\\SY.txt",L"C:\\SY.ZIP",false);
5 或者
6 MyFunZipCp(TEXT("C:\\SY.txt"),TEXT("C:\\SY.ZIP"),false);

 2, LPCTSTR和LPTSTR和char *究竟有什么区别

   "T"的含义就是如果定义了UNICODE,它就是宽字符版本,否则就是Ansi版本。
  LPTSTR:
  如果定义了UNICODE宏,那么LPTSTR = wchar_t*否则LPTSTR = char*
  如果定义了UNICODE宏,那么LPCTSTR = const wchar_t*,否则LPCSTR = const char*

  MSDN上的DataType上是这么说的,LPTSTR是什么呢?

  #ifdef UNICODE
   typedef LPWSTR LPTSTR;
  #else
   typedef LPSTR LPTSTR;
  #endif

  在unicode编码中(VS2010,VS2013等):而LPWSTR是针对wchar_t的

  在ansi编码中(VC6):LPSTR是针对char的,
  typedef CHAR *LPSTR;typedef char CHAR;可见如果没有定义UNICODE的话, char *就是LPTSTR,而const char *就是LPCTSTR,

  那个T表示的是TCHAR(char[ascii],wchar_t[UNICODE])

  所以,可以再程序中:使用char* pStr;

  (LPTSTR) pStr, 直接进行转化,(LPSTR或者LPWSTR的情形)。

 

 1 //Unicode 版本
 2 
 3 typedef wchar_t WCHAR;
 4 typedef WCHAR *PWCHAR;
 5 typedef WCHAR *LPWCH, *PWCH;
 6 typedef CONST WCHAR *LPCWCH, *PCWCH;
 7 typedef WCHAR *NWPSTR;
 8 typedef WCHAR *LPWSTR, *PWSTR;
 9 typedef WCHAR UNALIGNED *LPUWSTR, *PUWSTR;
10 
11 typedef CONST WCHAR *LPCWSTR, *PCWSTR;
12 typedef CONST WCHAR UNALIGNED *LPCUWSTR, *PCUWSTR;
13 
14 // Ansi版本
15 
16 typedef CHAR *PCHAR;
17 typedef CHAR *LPCH, *PCH;
18 
19 typedef CONST CHAR *LPCCH, *PCCH;
20 typedef CHAR *NPSTR;
21 typedef CHAR *LPSTR, *PSTR;
22 typedef CONST CHAR *LPCSTR, *PCSTR;
23 
24 #ifdef UNICODE(VS2013等IDE)
25     typedef WCHAR TCHAR, *PTCHAR;
26     typedef WCHAR TBYTE , *PTBYTE ;
27     typedef LPWSTR LPTCH, PTCH;
28     typedef LPWSTR PTSTR, LPTSTR;
29     typedef LPCWSTR PCTSTR, LPCTSTR;
30     typedef LPUWSTR PUTSTR, LPUTSTR; 
31     typedef LPCUWSTR PCUTSTR, LPCUTSTR;
32     typedef LPWSTR LP;
33 #else(VC6的开发环境)
34     typedef char TCHAR, *PTCHAR;
35     typedef unsigned char TBYTE , *PTBYTE ;
36     typedef LPSTR LPTCH, PTCH;
37     typedef LPSTR PTSTR, LPTSTR, PUTSTR, LPUTSTR;
38     typedef LPCSTR PCTSTR, LPCTSTR, PCUTSTR, LPCUTSTR;
39 #endif

 可以直接通过LPTSTR或者LPCTSTR 进行直接类型转化为适应于:Unicode编码下:LPWSTR,LPCWSTR  或者ANSI编码下:LPSTR, LPCSTR  的情形

  因为:LPTSTR,LPCTSTR可以通过编译器的当前的编码类型自动转换为相应的编码

  但是:当LPTSTR,LPCTSTR与直接的char* 或者w_char* 转化时,需要特别注意。

  在进行字符相关的API调用时:
  (1)直接转化成相应的类型;
  (2)可以采取“中庸”的API同时可以兼容:char* 或者w_char*

  如: strcpy、wcscpy与_tcscpy
C++标准库函数提供了字符和字符串的操作函数,并提供了其UNICODE版本,如:

  •     char *strcpy(char *strDestination, const char *strSource); 
  •     wchar_t *wcscpy(wchar_t *strDestination, const wchar_t *strSource);

wcscpy()即为strcpy()的宽字符版本,与_T类似的,Visual C++提供了类似的同名函数: 

    #ifdef  UNICODE   
        #define _tcscpy     wcscpy  
    #else  
        #define _tcscpy     strcpy  
    #endif 

  这样可以直接使用:_tcscpy来代替:strcpy用于asci等编码情形,或者wcscpy用于UNICode编码情形

  因为:TCHAR也可以适用于不同给的编码情形,所以采用TCHAR在实际的不同字符编码体系开发中比较好

因此我们建议这样书写代码:
    TCHAR src[] = _T("学习C++");  
    TCHAR dest[20];  
    _tcscpy(dest, src); 

  比如,在使用printf()的时候,我会尝试使用_tprintf()。

  同样的版本问题一样会困扰着main()函数:

  • main( int argc, char *argv[ ], char *envp[ ]);  
  • wmain( int argc, wchar_t *argv[ ], wchar_t *envp[ ]);
再来看_tmain()的定义:

    #ifdef  UNICODE   
        #define _tmain      wmain  
        #define _tWinMain   wWinMain  
    #else  
        #define _tmain      main  
        #define _tWinMain   WinMain  
    #endif 

  这就是为什么Win32控制台项目默认输出,提供一个_tmain()函数的缘故。


 

  刨根问底

Microsoft 专用

  为了简化各种国际市场的代码开发, Microsoft 运行库提供许多数据类型、例程和其他对象提供特定于 Microsoft 的 “一般文本映射”。

  这些映射。 TCHAR.H. 定义。 可以使用这些名称映射到可用于任何这三个生成字符集的通用代码:

  ASCII (SBCS) 使用 #define 语句,中, MBCS 或 Unicode,根据一个清单常数您定义。 一般文本映射是不符合 ANSI 的 Microsoft 扩展。

   

   

   

   char*风格的参数不支持Unicode

   

  CString,string,char*之间的转换

  这三种类型各有各的优点,比如CString比较灵活,是基于MFC常用的类 型,安全性也最高,但可移植性最差。string是使用STL时必不可少的类型,所以是做工程时必须熟练掌握的;char*是从学习C语言开始就已经和我 们形影不离的了,有许多API都是以char*作为参数输入的。所以熟练掌握三者之间的转换十分必要。

  以下我用简单的图示指出三者之间的关系,并以标号对应转换的方法。

  https://images0.cnblogs.com/blog/96158/201307/03040242-4ef3a7f27ddb42f1a6866212ac9f6c01.jpg

 1 1 string to CString   
 2   CString.format("%s",string.c_str()); 
 3 
 4 2 CString to string
 5 string str(CString.GetBuffer(str.GetLength()));
 6 
 7 3 string to char *
 8 char *p=string.c_str();
 9 
10 4 char * to string
11 string str(char*);
12 
13 5 CString to char *
14 strcpy(char,CString,sizeof(char));
15 
16 6 char * to CString
17 CString.format("%s",char*);
18  CString的format方法是非常好用的。string的c_str()也是非常常用的,但要注意和char *转换时,要把char定义成为const char*,这样是最安全的。
19  
20 以上函数UNICODE编码也没问题:unicode下照用,加个_T()宏就行了,像这样子_T("%s")

 

CString与LPCWSTR、LPSTR、char*、LPWSTR等类型的转换

一.CString与LPCWSTR 

    两者的不同:LPCWSTR 是Unicode字符串指针,初始化时串有多大,申请空间就有多大,以后存贮若超过则出现无法预料的结果,这是它与CString的不同之处。而CString是一个串类,内存空间类会自动管理。

    CString转换成LPCWSTR

    方法一:CString strFileName;

                     LPCWSTR lpcwStr = strFileName.AllocSysString();

    方法二:CString str=_T("TestStr"); 
                    USES_CONVERSION; 
                    LPCWSTR lpcwStr = A2CW((LPCSTR)str);

    MFC中CString和LPSTR是可以通用,其中A2CW表示(LPCSTR)  -> (LPCWSTR),USER_CONVERSION表示用来定义一些中间变量,在使用ATL的转换宏之前必须定义该语句。

    LPCWSTR转换成CString

    LPCWSTR lpcwStr = L"TestWStr"; 
    CString str(lpcwStr);

 CString str;

LPWSTR  lpstr = (LPWSTR)(LPCWSTR)str;

二.CString与LPSTR转换

     CString转换成LPSTR:

    方法一:CString strFileName;

                    LPSTR lpStr = strFileName.GetBuffer();

                    strFileName.ReleaseBuffer();

     方法二:CString strFileName;

                     LPSTR lpStr = (LPSTR)(LPCSTR)strFimeName;

      LPSTR转换成CString:

                      LPSTR lpStr = L"TestStr"; 
                      CString str(lpStr);

      注意:CString和LPCSTR可直接转换,如下:

                     CString str;

                     LPCSTR lpcStr = (LPCSTR)str;

三.CString和char*转换
       CString转换成char*
       方法一:CString str;
                       char* p = str.GetBuffer();
       方法二:CString str;
                       char* p = (LPSTR)(LPCSTR)str;
       char*转换成CString
                       char* p = "test";
                       CString str = ("%s",p);

四.String和int、float的转换

        可以使用atoi,atof,atol等函数来完成。

五.LPSTR(char*)和LPWSTR的转换

        可以使用下面的ATL宏来进行,最好是将变量定义成TCHAR、LPTSTR等T类型,可以避免转换。

ATL宏介绍:

     A2BSTR   OLE2A             T2A            W2A 
     A2COLE   OLE2BSTR    T2BSTR    W2BSTR 
     A2CT         OLE2CA         T2CA          W2CA 
     A2CW        OLE2CT         T2COLE    W2COLE 
     A2OLE       OLE2CW       T2CW         W2CT 
     A2T            OLE2T            T2OLE        W2OLE 
     A2W           OLE2W          T2W             W2T

    A :ANSI 字符串,也就是 MBCS。 
    W、OLE 宽字符串,也就是 UNICODE。 
    T 中间类型T。如果定义了 _UNICODE,则T表示W;如果定义了 _MBCS,则T表示A 
    C const 的缩写

利用这些宏,可以快速的进行各种字符间的转换。使用前必须包含头文件,并且申明USER_CONVERSION;使用 ATL 转换宏,由于不用释放临时空间,所以使用起来非常方便。但是考虑到栈空间的尺寸(VC 默认2M),使用时要注意几点:

    1、只适合于进行短字符串的转换; 
    2、不要试图在一个次数比较多的循环体内进行转换; 
    3、不要试图对字符型文件内容进行转换,因为文件尺寸一般情况下是比较大的; 
    4、对情况 2 和 3,要使用 MultiByteToWideChar() 和 WideCharToMultiByte();

void Func1(LPSTR lpStr);

void Func2(LPWSTR lpwStr);

TCHAR   name[256];

TCHAR*   pName = new  TCHAR[256];

Func1(name); // Func1(pName);

Func2(name); // Func2(pName);

注意在VS2005中上面用红色标记的代码已经不成立。

VS2005中CString已经改为宽字符型,一些转换如下:

char name[10];
 TCHAR sex[5] ;
 char *p = name;
 TCHAR *pw = sex;

 LPSTR lpstr = name;
 LPCSTR lpcstr = name;
 lpcstr = lpstr;
 
 lpstr = p;
 p = (char*)sex;
 pw = (WCHAR*)name;
 LPWSTR lpwstr = (LPWSTR)lpstr;
 lpwstr = (LPWSTR)lpcstr;
 LPCWSTR lpcwstr = (LPCWSTR)lpstr;
 lpcwstr = (LPCWSTR)name;

 CString str(lpstr);
 CString str1(lpcstr);
 CString str2(lpwstr);
 CString str3(lpcwstr);
 CString str4(name);
 CString str5(sex);

 lpwstr = (LPWSTR)(LPCWSTR)str;
 lpstr = (LPSTR)(LPCWSTR)str; lpcstr = (LPCSTR)(LPCWSTR)str;

 p = (char*)str.GetBuffer();
 pw = str.GetBuffer();

可以看出转换更加简单了,基本上可以直接转换,A2W等宏基本上不需要啦

 

CString:我们首先要了解 CString 是一种很特殊的 C++ 对象,它里面包含了三个值:

(1)一个指向某个数据缓冲区的指针、

(2)一个是该缓冲中有效的字符记数以及

(3)一个缓冲区长度。有效字符数的大小可以是从0到该缓冲最大长度值减1之间的任何数(因为字符串结尾有一个NULL字符)。

字符记数和缓冲区长度被巧妙隐藏。

  LPCTSTR 操作符(或者更明确地说就是 TCHAR * 操作符)在 CString 类中被重载了,该操作符的定义是返回缓冲区的地址,因此,如果你需要一个指向 CString 的 字符串指针的话

  CString s("GrayCat");  LPCTSTR p = s;
   CString转化成char* 之二:使用 CString 对象的 GetBuffer 方法;
  这是 GetBuffer 的第一种用法,也是最简单的一种,不用给它传递参数,它使用默认值 0,意思是:"给我这个字符串的指针,我保证不加长它"。当你调用 ReleaseBuffer 时,字符串的实际长度会被重新计算,然后存入 CString 对象中。
  
  LPTSTR p = s.GetBuffer(1024);
  调用这个函数后,你不仅获得了 字符缓冲区指针,而且同时还获得了长度至少为 1024 个字符的空间(注意,我说的是"字符",而不是"字节",因为 CString 是以隐含方式感知 Unicode 的)。
  
 
 

转载于:https://www.cnblogs.com/icmzn/p/5713209.html

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值