其實還可能出現其它類似的問題,如:
error C2664: “fopen”: 不能將參數 1 從“CString”轉換為“const char *”
error C2039: “strcpy”: 不是“ATL::CStringT<BaseType,StringTraits>”的成員
但是程式在VC6下編譯得很好,經過研究發現是設定上有所不同。在VC6中,預設使用MBCS編碼,即多位元組字元;而VC8、VC7預設的是Unicode編碼,所以...
關於這兩種編碼有何不同,我引用了網上的一篇文章,由於作者匿名,只能在此感謝:
http://pc.nengbang.cn/group_thread/view/id-2603
在VC6中,預設使用MBCS編碼,即多位元組字元,實際就是支援大於0x80的ASCII碼。這樣,一個中文字可以表示為2個位元組,GB2312就是這樣表示的。
VC6的預設安裝是不帶UNICODE庫的,要在VC6中寫UNICODE程式,必須安裝CRT和MFC的Unicode庫。
要使你的程式支援Unicode,要在你的項目屬性中去掉"_MBCS"宏定義,增加"UNICODE"和"_UNICODE"兩個宏定義。(注意,這兩個都應該加上,因為CRT和MFC使用UNICODE定義,而STL則使用_UNICODE)
如果你的程式是MFC的,則Unicode版MFC庫的進入點是wWinMainCRTStartup。
為了方便開發人員,VC6中提供了Tchar.h,裡面定義了一些宏用來協助寫兩種編碼都相容的代碼。
類型
一般文本 資料類型名稱 _UNICODE 和 _MBCS 未定義 _MBCS 已定義 _UNICODE 已定義
_TCHAR char char wchar_t
_TINT int int wint_t
_TSCHAR signed char signed char wchar_t
_TUCHAR unsigned char unsigned char wchar_t
_TXCHAR char unsigned char wchar_t
_T 或 _TEXT 無效(由前置處理器移除)無效(由前置處理器移除)L(將後面的字元或字串轉換成相應的 Unicode 形式)
CRT中的相關函數在Tchar.h中都定義了相應的替代,基本是將str換成了_tcs,比如:CRT中的unsigned int strlen(const char *)現在是unsigned int _tcslen(const TCHAR*),在Uniocde時,將被替換為unsigned int _wcslen(const wchar_t)*,而在MBCS時,會被替換為unsigned int _mcslen(const char*)。
看,寫Unicode和MBCS相容的代碼挺容易的吧,我總結了一些替換規則
1 將char換成TCHAR (unsigned char必須去掉unsigned)
2 將str函數換成_tcs函數
3 將字串常量定義加要_T("")宏
4 printf函數族必須修改為wprintf,不過要注意千萬不要使用wprintf函數來解析char型
很多時候程式中既需要Unicode,又需要使用ASCII,這時需要用到作業系統的2個API
WideCharToMultiByte用來將Unicode字串轉化為MBCS的
MultiByteToWideChar用來將MBCS字串轉化為Unicode的
一些注意事項:
在Unicode編碼下,sizeof沒那麼可靠了,memset( 0 sizeof())的習慣用法可能會出大錯,改成memset(0sizeof()/szieof(TCHAR))就沒事了,呵呵
在Unicode下,一個中文字元就是一個字元,len = strlen() / 2;這樣可不行了
用VC6進行UNICODE編程
最近試圖將自己的程式編譯成Unicode版本,費了不少力氣,相關內容整理如下,適用於VC6,但VC7、VC8應該也差不多的(後者建立項目預設即按Unicode編譯)。
1. 添加 UNICODE 和 _UNICODE 預先處理定義
位置:Project Settings -> C/C++ -> Preprocessor definitions
添加了這兩個定義後,MFC的一些內建類型如 TCHAR、CString 都將轉為支援寬字元類型(wchar_t)
2. 使用寬字元相互關聯類型,如:
char -> TCHAR、char * -> LPTSTR、const char * -> LPCTSTR
3. 對字串常量使用 _T() 宏
4. 替換C庫中的中字串操作函數,如 strlen -> _tcslen、strcmp -> _tcscmp 等
類似的還有C庫中字串與數位轉換函式,如 atoi -> _ttoi、itoa -> _itot 等
5. 將 Project Settings -> link -> Output -> Entry Point 設為 wWinMainCRTSTartup
否則會有如下錯誤:
msvcrtd.lib(crtexew.obj) : error LNK2001: unresolved external symbol _WinMain@16
6. C++標準庫中的string,有對應的寬字元版本wstring,兩者均為basic_string的特化版本
可在StdAfx.h中:
#ifdef _UNICODE
#define tstring wstring
#else
#define tstring string
#endif
然後在代碼中使用 tstring 即可,類似的還有 fstream/wfstream、ofstream/wofstream 等
7. 寬字元版本的英文字元仍可直接與整型值進行比較,如:
CString s = _T("ABC");
ASSERT(s[0] == 'A');
8. 對於仍需使用ANSI字串的地方,如第三方類庫的介面,仍可繼續使用;如需進行Unicode字串和ANSI字串的互轉換,可使用 MultiByteToWideChar 和 WideCharToMultiByte