1. 程式人生 > >關於Unicode和ANSI字符集處理

關於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()即可解決問題。第一次寫部落格,算是個開始吧,格式也沒有排版好,關於技術上的東西也不是很準確,不過算是一個開始吧。