程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> Windows 字符串詳解及轉換

Windows 字符串詳解及轉換

編輯:關於C語言

最近一直在做基於Windows的開發,而windows的開發當中最讓我迷惑的一個問題就是無窮無盡的字符串類型,char*, wchar *, lpstr, lptstr, lpctstr等等,然後還要經常涉及到其中的相互轉換,所以想系統的研究一下所有的windows類型及其相互轉換的關系。


1.字符類型

講到字符串,首先首先需要了解的是字符,在Windows中主要包含兩種字符,一種是ANSI字符,另一種是Unicode字符使用UTF16編碼,即每個字符編碼為2個字節)。C++中表示ANSI字符的關鍵字是char,然後每個字符的長度是1;而表示Unicode字符的類型是wchar_t,每個字符的長度是2。而為了和語言有一些區別,Windows又定義了自己的數據類型這是微軟最煩的一點了!)

typedef charCHAR; //8位字符

typedefwchar_t WCHAR;//16位字符


2.字符串

講完了字符類型,現在開始講字符串了,Windows定義了非常多的字符指針或字符串指針

// 8位字符指針

typedef CHAR*PCHAR;

typedef CHAR*PSTR;

typedef CONSTCHAR *PCSTR

// 16位字符指針

typedef WCHAR*PWCHAR;

typedef WCHAR*PWSTR;

typedef CONSTWCHAR *PCWSTR;


首先介紹的是上面定義的六種字符指針,名字還是比較好記的,P代表Point指針),W代碼Unicode,C代表Const常量),CHAR 和STR代碼字符。所以PCHAR和PSTR的意思是一樣的就是ANSI類型的字符指針;而PWCHAR和PWSTR的類型也是一樣的,就是Unicode類型的字符指針;PCSTR和PCWSTR分別代表常量ANSI字符指針和常量Unicode字符指針什麼?不知道啥叫常量?請出門左轉《EffectiveC++》條款03,盡可能使用Const)。

同時,Windows為了保證使用ANSI或Unicode都能通過編譯,又定義了下面的類型,這些宏會自動檢測是否定義了Unicode。


#ifdef UNICODE

typedef WCHAR TCHAR, *PTCHAR, PTSTR;

typedef CONST WCHAR *PCTSTR;

#define __TEXT(quote) quote // r_winnt

#define __TEXT(quote) L##quote

#else

typedef CHAR TCHAR, *PTCHAR, PTSTR;

typedef CONST CHAR *PCTSTR;

#define __TEXT(quote) quote

#endif

#defineTEXT(quote) __TEXT(quote)


從上面可以看出,如果定義了UNICODE宏,TCHAR等同於WCHAR, PTSTR和PTCHAR等同於PWCHAR和PWSTR,而如果沒有定義UNICODE宏,則TCHAR等同於CHAR,PTSTR和PTCHAR等同於PCHAR和PSTR;PCTSTR也是同理。

同時還要注意的是,這裡添加了TEXT宏,TEXT等同於__TEXT宏,__TEXT則能自動將字符串轉換為ANSI類型字符串或UNICODE類型字符串。而L加字符串則自動表示為Unicode類型字符串。

而在很多場合還會出現LPSTR,LPCHAR, LPCSTR,這個L是對應於16位OS而已代表long,也就是長指針,而現在32位的OS上所有前面加L的類型和不加L的類型已經沒有任何區別了。

下一種類型是BSTR, BSTR是一個Pascal-Style字符串和C-Style字符串的混合物,在COM中用的非常多,因為COM接口希望字符串可以用在所有語言中,繼而定義了這個類型。Pascal-style字符串是在存儲字符串的首幾個字節會用在記錄字符串的長度,所以這種類型的字符串不需要在末尾添加額外的字符標示結束。所以BSTR字符串的意思是在字符串的首幾個字節存儲字符串的長度,而字符串的結尾以\0結束。但是對BSTR字符串取下標時則是指向第一個字符而不是字符串長度,這樣又利用C-Style的程序使用。

然後還有兩個標准的字符串類, String和CString。String是標准C++中提供的程序庫,而CString則是MFC中提供的字符串類。

好吧,我們最後來總結一下所有的字符串類型。

按照不同的style字符類型分有五類:

C-Style ANSI類型字符串:CHAR *,PSTR, LPSTR, LPCSTR, PCHAR.

C-StyleUnicode類型字符串:WCHAR *, PWSTR, LPWSTR, PWCHAR,LPCWSTR.

C-Style 同時兼容ANSI和Unicode類型字符串:TEXT,__TEXT(), TCHAR *, PTSTR, LPTSTR, PCTSTR, LPCTSTR.

C-style和Pascal-Style兼並的字符串:BSTR

兩種C++類:String, CString.

不同類型字符串組合的含義技巧是:

L (無效) + P(字符指針) + 不加(ANSI類型)或W(Unicode類型)  或T (ANSI 或Unicode類型) + 不加(非常量字符串)或C(常量字符串) + STR或CHAR(CHAR結尾時前面不能加C).


3.轉化

下面是重頭戲,也就是不同類型直接的轉換技巧:

轉換的順序是:


1)首先先講可以等號直接轉換的:

CHAR * ==PSTR, LPSTR

WCHAR * ==PWSTR, LPWSTR

TCHAR * ==PTSTR, LPTSTR

原因也很明顯,其實都是一種類型嘛。

同時CHAR *類型和WCHAR *也能同時轉換為TCHAR *,反之不行。

而PSTR可以直接等於轉換PCSTR,PWSTR等於轉換為PWCSTR,反之則不行。


2)PCSTR轉換為PSTR

一般情況下可以使用C語言方式的強制類型轉換,或者C++方式的Const_cast將const去掉。


3)PSTR轉換為PWSTR

一般有兩種方式,第一種是簡單的W2A或A2W,W2A代表將PWSTR轉換為PSTR,反之A2W表示將PSTR轉換為PWSTR,見下面的code:

USES_CONVERSION;

PWSTR wszText = L"1.Unicode字符轉換為ANSI;";

PSTR szText="2.ANSI字符轉換成Unicode.";

printf("%s\n",W2A(wszText));

wprintf(L"%s\n",A2W(szText));


注意一點是不要在大循環或者非常長的函數中使用W2A或A2W,具體分析看http://www.cnblogs.com/rainbowzc/archive/2009/09/07/1562168.html。

另一種轉換方法是MultiByteToWideChar和WideCharToMultiByte。MultiByteToWideChar表示將ANSI字符串轉換為Unicode字符串,而WideCharToMultiByte則是將Unicode字符串轉換為ANSI字符串。

MultiByteToWideChar的形式是

int MultiByteToWideChar(

UINT CodePage,

DWORD dwFlags,

LPCSTRlpMultiByteStr,

intcchMultiByte,

LPWSTR lpWideCharStr,

intcchWideChar

);

6個參數的含義為:CodePage多字符所對應的的字符集,一般是CP_ACP), dwFlags(一些標准位,一般不需要使用,置0即可),lpMultiByteStr多字符的地址),cchMultiBytes多字符的字符串長度,相當於字符串的字節數,如果是1,則由函數判斷長度), lpWideCharStr寬字符的地址),cchWideChar寬字符的字符長度,相當於字符串的個數)。上面的兩個長度都是包含‘\n’的長度。

如果lpWideCharStr不為NULL,返回轉換成功的長度;如果lpWideCharStr為NULL,返回lpMultiByteStr的字符個數不是字符串長度!!!)。

常用的用法為:

//先將lpWideCharStr置成NULL,從而得到szText的長度。

int iBuffSize =::MultiByteToWideChar(CP_ACP, 0, szText, -1, NULL, 0);

//判斷字符長度是否大於0

if (iBuffSize> 0)

{

   LPWSTRwszString = new wchar_t[iBuffSize+1];

   int nChars= ::MultiByteToWideChar(CP_ACP, 0, szText, -1,    wszString, iBuffSize);

   //這是擔心轉換失敗,從而nChars為0,再講wszString置成空字符串

   nChars= nChars < iBuffSize ? nChars:iBuffSize;

   wszString[nChars]= 0;

}


另一個是寬字符到多字符:

intWideCharToMultiByte(

UINT CodePage,

DWORD dwFlags,

LPCWSTR lpWideCharStr,

int cchWideChar,

LPSTR lpMultiByteStr,

int cchMultiByte,

LPCSTR lpDefaultChar,

LPBOOL pfUsedDefaultChar

);


這裡比MultiByteToWideChar多兩個參數,而前面的六個參數都是一樣的,lpDefaultChar的作用是當函數遇到一個不能轉換的寬字符時,會用lpDefaultChar來代替,如果lpDefaultChar為NULL時,則用?代替。pfUsedDefaultChar的作用是如果有一個字符沒有成功轉換,則pfUsedDefaultChar為TRUE,否則為FALSE。


int iBuffSize =::WideCharToMultiByte(CodePage, 0, szString, -1, NULL, 0,NULL, false);

if (iBuffSize > 0 )

{

   m_pString= new char[iBuffSize];

   ::WideCharToMultiByte(CodePage, 0,szString, -1, m_pString, iBuffSize, NULL, false);

}


4)PSTR和BSTR的相互轉換

首先是PSTR轉換為BSTR:

BSTR bstrText = _bstr_t(“thisis a bstr”);

BSTR轉換為PSTR:

_bstr_b b = bstrText;

PSTR lpszText = b;





  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved