vs2010與vc6中字符轉換的問題

 一、

使用函數_tcscpy_s:

CString theString( "This is a test" ); 
int    sizeOfString = (theString.GetLength() + 1); 
LPTSTR  lpsz = new TCHAR[ sizeOfString ]; 
_tcscpy_s(lpsz, sizeOfString, theString);

最後再轉換一下lpsz爲const型的

LPTSTR在UNICODE環境下編譯是wchar_t類型

 

二、

CString str = _T("Hello World!");

char szStr[256] = {0};

wcstombs(szStr, str, str.GetLength());

const char * p = szStr;



其實還可能出現其它類似的問題,如:

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章