UNICODE 編程入門

來源:互聯網
上載者:User
 如果你編寫的程式是針對非英語國家的使用者,如中國、日本、東歐和中東地區,那麼你一定要熟悉 UNICODE 字元集。尤其是用 Visual C++/MFC 編寫針對上述國家和地區的使用者的程式時,如果你想讓自己的應用程式得到更廣泛的使用者,那麼必須考慮代碼 UNICODE 的相容性,也就是說它既在 ASCII 模式下運行 ,也能在UNICODE 模式下運行。本文將介紹 UNICODE 的一些基本編程知識,澄清很多人(包括我自己)在這個問題上存在的模糊認識。對於任何使用 Visual C++ 和/或 MFC 編程的人來說,這篇文章肯定值得一讀。

UNICODE到底是什嗎?

    UNICODE 是目前用來解決 ASCII 碼 256 個字元限制問題的一種比較流行的解決方案。大家知道,ASCII 字元集只有256個字元,用 0-255 之間的數字來表示。包括大小寫字母、數字以及少數特殊字元;如標點符號、貨幣符號等。對於大多數拉丁語言來說,這些字元已經夠用。但是,許多亞洲和東方語言所用的字元遠遠不止256個字元。有些超過千個。人們為了突破 ASCII 碼字元數的限制,試圖用一種簡單的方法來針對超過256個字元的語言編寫電腦程式。於是 UNICODE 應運而生。UNICODE 通過用雙位元組來表示一個字元,從而在更大範圍內將數字代碼映射到多種語言的字元集。

Visual C++的解決方案

    作為軟體開發人員,如何熟練有效地使用 UNICODE 呢?如果你正在用 Visual C++ 編寫程式,UNICODE 相容性意味著你的程式是否具有國際化特徵,也就是說你的應用程式是針對本地市場還是國際市場。一旦你作出了決定,那麼就得在代碼中實現具體細節。好在 Visual C++ 提供了很多內建功能來支援 UNICODE,在建立工程時就可以利用 Visual C++ 提供的這些功能。在產生應用程式架構代碼之前,AppWizard 允許開發人員決定是否支援 UNICODE。Win32 SDK 包含有一些資料類型遵循 UNICODE 編碼規則,MFC 以宏的形式提供了將一般文本轉換成 UNICODE 資料類型的途徑。開發人員只需要稍微改變一下編寫代碼的習慣便可以輕鬆編寫支援 UNICODE 的應用。

字串     C 程式員一般是用 char 關鍵字象下面這樣來聲明一個字串數組:

       char str[100];       

象下面這樣聲明函數原形:

       void strcpy( char *out, char *in );        

為了將上面的聲明改成支援雙位元組的 UNICODE 字元集,可以用下面的方法:

       wchar_t str[100];        

或者

       void wcscpy( wchar_t *out, wchar_t *in );        

    此外,微軟還提供一種通過預先處理指令來實現 UNICODE。每當用 Visual C++ 建立新工程時,只要確定是否支援另外一種字元集,則 AppWizard 將會在標頭檔中插入預先處理指令。這些指令告訴編譯器程式想要支援何種字元集。這樣在使用VC++提供的通用資料類型時,編譯器將用相應的資料類型把通用資料類型替換成所需要支援的字元集。這樣很容易將代碼重新編譯成支援其它字元集的程式。
    為了在 Visual C++ 6.0 中啟用 UNICODE 標準,可以這樣做:開啟工程檔案後,從主菜單中選擇“Project | Settings”開啟工程設定對話方塊 => 然後選擇“C/C++”標籤 => 在“Preprocessor definitions”編輯框中添加 UNICODE 或者 _UNICODE 預先處理巨集指令。一所示:


圖一 Project Settings 對話方塊

注意這裡的 UNICODE 和 _UNICODE 有什麼區別呢?前者沒有底線,專門用於 Windows 標頭檔;後者有一個首碼底線,專門用於 C 運行時標頭檔。
在代碼中,凡是用關鍵字 char  的地方都用 TCHAR 取代;凡是用 char * 的地方都用 LPTSTR 取代;凡是定義在雙引號中的字串常量(如"VCKBASE Online Journal")都用 TEXT 宏重寫:

       TEXT("VCKBASE Online Journal");       

TEXT 宏的主要作用是當定義了 UNICODE/_UNICODE 預先處理指令時,字串被標誌為雙位元組字元串,否則字串被標示為 ANSI 字串。TEXT 的定義如下:

      TEXT(LPTSTR string // ANSI 或者 Unicode 字串);參數   string 為字串指標,指向被解釋的 Unicode 或者 ANSI 字串

在文檔中 微軟提供了包括通用類型在內的幾種資料類型都與 ASCII 和 UNICODE相容。這一點可以參考微軟線上文檔有關“通用資料類型和資料類型”的章節。

例子代碼

下面通過一些簡單的例子來進一步探討 UNICODE 編程。

使用 ASCII 字元集的“Hello, World”:

//*********************************
// 用 MFC 實現的"Hello World!" 代碼
//*********************************

//hello.cpp#include <afxwin.h>// Declare the application classclass CHelloApp : public CWinApp{public:virtual BOOL InitInstance();};// Create an instance of the application classCHelloApp HelloApp;// Declare the main window classclass CHelloWindow : public CFrameWnd{CStatic* cs;public:CHelloWindow();};// The InitInstance function is called each// time the application first executes.BOOL CHelloApp::InitInstance(){m_pMainWnd = new CHelloWindow();m_pMainWnd->ShowWindow(m_nCmdShow);m_pMainWnd->UpdateWindow();return TRUE;}// The constructor for the window classCHelloWindow::CHelloWindow(){// Create the window itselfCreate(NULL, "Hello World!", WS_OVERLAPPEDWINDOW,CRect(0,0,200,200));// Create a static labelcs = new CStatic();cs->Create("hello world", WS_CHILD|WS_VISIBLE|SS_CENTER,CRect(50,80,150,150), this);}

修改上面的代碼使之支援 UNICODE 字元集,串常量必須要改成對應的 UNICODE 字元。方法是對串常量使用TEXT 宏。這個宏將告訴前置處理器檢查使用什麼樣的字元標準:

// The constructor for the window classCHelloWindow::CHelloWindow(){// Create the window itselfCreate(NULL, TEXT("Hello World!"), WS_OVERLAPPEDWINDOW,CRect(0,0,200,200));// Create a static labelcs = new CStatic();cs->Create( TEXT("hello world!"), WS_CHILD|WS_VISIBLE|SS_CENTER,CRect(50,80,150,150), this);}

當前置處理器碰到通用資料類型,它便檢查 AFXWIN.H 標頭檔的 _UNICODE 定義。然後根據 UNICODE 定義插入相應的的資料類型。

下面的這個例子使用 Win32 API 函數和通用資料類型設定 C 盤的卷標。

//******************
// 設定 C 盤的卷標
//******************

// drvsvl.cpp#include <windows.h>#include <iostream.h>void main(){BOOL success;char volumeName[MAX_PATH];cout << "輸入新的 C 盤卷標:";cin >> volumeName;success = SetVolumeLabel("c:\\", volumeName);if (success)cout << "成功\n";elsecout << "錯誤碼:" << GetLastError() << endl;}

通過使用 TCHAR 資料類型,將這段代碼最上面的字元數組聲明為兩個位元組的字元。TEXT 宏再次被用於字串常量:

void main(){BOOL success;TCHAR volumeName[MAX_PATH];cout << TEXT("輸入新的 C 盤卷標: ");cin >> volumeName;success = SetVolumeLabel(TEXT("c:\\" ), volumeName);if (success)cout << TEXT("成功\n");elsecout << TEXT("錯誤碼:") << GetLastError() << endl;} 

Visual C++ 中的通用資料類型

    Visual C++ 提供了幾種 MFC 專用的資料類型用於建立具有國際化特性的應用程式。這些定義很通用,完全可以在 UNICODE、ASCII、DBCS (雙位元組字元集) 和 MBCS (多位元組字元集)。由於篇幅所限,本文不打算涉及所有上面提到的這些字元集。有關它們的詳細資料請參考相關資料。MFC 提供了一種透明的方式來實現這些字元集。通用資料類型的映射到哪個字元集以及映射方式是根據工程的設定決定的,預設值為 ASCII 模式,其它幾個可選項是 MBCS、DBCS 或者 UNICODE。本文主要討論 UNICODE,所以下表中只列出了 ASCII 與 UNICODE 字元之間的映射關係:

表一:

通用 MFC 資料類型 映射到 ASCII 映射到 UNICODE 注釋
_TCHAR char wchar_t _TCHAR 是一個映射宏,當定義 UNICODE 時,該資料類型映射到 wchar_t,如果沒有定義 UNICODE,那麼它映射到 char。
_T 或 _TEXT char 常量字串 wchar_t 常量字串 功能與宏相同,在 ASCII 模式下,它們被忽略,也就是說被前置處理器刪除掉,但是如果定義了UNICODE, 則它們會將常量字串轉換成等價的 UNICODE 。
LPTSTR char*, LPSTR(Win32) wchar_t* 可移植的32位字串指標。它將字元類型映射到工程設定的類型。
LPCTSTR const char*, LPCSTR(Win32) const wchar_t* 可移植的32位常量字串指標。它將字元類型常量映射到工程設定的類型。

使用表一中列出的通用資料類型,開發人員可以保證所建立的工程始終是針對一種字元集,這些通用資料類型就相當於預留位置,在編譯時間被特定的位元組所替代,使得應用程式在 ASCII 和 UNICODE 模式下都能運行。但是,有一點要特別注意,那就是上述的通用資料類型為微軟專有,與 ANSI 標準並不相容。有關微軟提供的這些通用資料類型詳細描述請參考 MSDN 庫文檔。

有關技術注釋

    為了成功編譯支援 UNICODE 的 MFC 程式,必須使用 MFC 的 UNICODE 版本庫。該庫在定製安裝Visual C++ 時是個可選安裝項。
    有一點很重要:那就是不使用 UNICODE 標準在外觀上並不影響程式的執行。也就是說,上面提到過的代碼不管設沒設定 _UNICODE 產生選項,最終都能產生正常啟動並執行程式。當開發人員使用多個版本的Win32 API函數時才會出現問題。
    在使用多個版本的 Win32 API函數(任何有字元或字串作為參數的 Win32 API函數)時,編譯器根據是否設定 _UNICODE 指令來決定調用正確的函數。如果沒有定義_UNICODE,那麼編譯器將預設調用 ASCII 版本函數。

結束語

    綜上所述可以看到,編譯 UNICODE 版本的程式並不難。只是在編寫代碼時記住函數調用上些微的變化。微軟為此提供的擴充是開發人員能夠以透明的方式選擇所用的字元集,為應用軟體的國際化開啟了方便之門。
    Jeffrey Richter 在他的《Windows 核心編程》(機械工業出版社-王建華、張煥生、侯麗坤等譯)一書中專門用一章討論了 UNICODE。翻譯得也不錯。有興趣的朋友不妨找來看看。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.