關於Unicode和ANSI字符集處理
最近重溫了一下孫鑫的《MFC深入詳解》,遇到一個關於字串處理的問題,孫鑫的原始碼如下:
void CAddDlg::OnBnClickedButtonAdd()
{
int num1,num2,num3;
TCHAR c1[10],c2[10],c3[10];
GetDlgItem(IDC_EDIT_ADD)->GetWindowText(c1,10);
GetDlgItem(IDC_EDIT_BEADD)->GetWindowText(c2,10);
num1 = atoi(c1);
num2 = atoi(c2);
num3 = num1+num2;
itoa(num3,c3,10);
GetDlgItem(IDC_EDIT_SUM)->SetWindowText(c3);
}
這裡孫鑫是在VC6.0中進行開發,我用的是VS2008,使用孫鑫的程式碼,會有以下報錯:
“atoi”: 不能將引數 1 從“TCHAR [10]”轉換為“const char *”
這裡先介紹以下TCHAR 是一個什麼型別的變數,通過轉到定義,發現其在Windows中定義如下:
#ifdef
UNICODE
typedef
wchar_t TCHAR;
#else
typedef
char TCHAR;
#endif
這裡char型別大家可以肯定在C++的一些基礎書籍上接觸過,表示字元變數,其中儲存的是字元。書中的字元都是採用的ASCII編碼。
而wchar_t 其實就是Unicode中的字元型別。所以TCAHR其本身的型別是根據是否定義UNICODE巨集來確定的,使用這種方式來定義字元變數是為了程式碼的可移植性,那麼如何判斷是否定義了UNICODE巨集,我們進入工程的屬性選單,會彈出如下對話方塊:
在其中可以選擇編碼方式是Unicode還是ANSI編碼,這裡我猜想如果選擇Unicode編碼則會定義UNICODE巨集吧。
在有了以上鋪墊後理解這個錯誤就很容易了,VS2008中預設的都是採用Unicode編碼,因此這裡TCHAR的型別就是wchar_t 型別的,而atoi()函式的定義是這樣的:int atoi(const char *nptr);明顯引數型別是不匹配的,所以會有如上的報錯。
所以解決方法其實有兩種,方法一:將工程的編碼方式由Unicode編碼改為多位元組編碼,也即為ANSI編碼。這時候TCHAR的型別是char型別的,既不會報錯。
方法二:
這種方法不用atoi()函式,其實對於字串的處理函式,根據字元編碼型別有兩種:
ANSI UNICODE 通用
(char.h) (wchar.h) (tchar.h)
char wchar_t TCHAR
char * wchar_t * PTCHAR (PTSTR,LPWSTR,PWSTR,WCHAR)
printf wprintf _tprintf
scanf wscanf _tscanf
atoi _wtoi _ttoi
atol _wtol _ttol
itoa _itow _itot
ltoa _ltow _ltot
atof _wtof _tstof
strlen wcslen _tcslen
strcat wcscat _tcscat
strcpy wcscpy _tcscpy
strcmp wcscmp _tcscmp
這裡使用通用的函式_ttoi()即可解決問題。第一次寫部落格,算是個開始吧,格式也沒有排版好,關於技術上的東西也不是很準確,不過算是一個開始吧。