關於C++編程中字符與字符串的處理

一、

Unicode標準:

每個Unicode字符都是使用UTF-16編碼,UTF-16將每個字符編碼爲2個字節,UTF-16在節省空間和簡化編碼之間提供了一個良好的折衷。

ANSI標準:

使用UTF-8編碼,一個字符使用一個字節,佔8位。c語言的char類型用來表示一個8位的ANSI字符。

 

二、  

WIndows系統與Unicode標準:

自Windows NT起,Windows所有版本都採用Unicode標準,所有核心函數都採用Unicode字符串,如果調用一個函數傳入的參數是ANSI字符串,那麼函數會先將其轉換衝Unicode字符串,再傳給操作系統,如果希望函數返回ANSI字符串,那麼操作系統會先將Unicode字符串轉換成ANSI字符串,這些轉換都在幕後進行的,因此係統會產生時間和內存上的消耗。

 

三、

Microsoft的C/C++編譯器與Unicode字符:

現在Microsoft的C/C++編譯器定義了一個內建的數據類型wchar_t,它表示一個16位的Unicode(UTF-16)字符,在默認情況下,VS建立一個新項目時,是使用Unicode標準字符的。

聲明Unicode字符或字符串的方法:wchar_t c = L'A';  在前面加個L表示通知編譯器該字符(串)應當編譯爲Unicode字符。輸出要用std::wcout。

 

四、

源代碼如何保持一致性:

windows開發團隊與c語言稍有區別,他們在Windows頭文件WinNT.h中定義了以下數據類型:

typedef char CHAR ;  

typedef wchar_t WCHAR;

 

//指針

typedef  CHAR *PCHAR;

typedef  CHAR *PSTR;  

typedef  CONST CHAR *PCSTR;  

 

typedef WCHAR PWCHAR;

typedef WCHAR PWSTR;

typedef  CONST WCHAR *PCWSTR;  

 

在源代碼中,具體使用哪種字符類型不重要,重要的是保持一致性,增加代碼的可維護性, WinNT.h中定義了以下類型和宏:

#ifdef UNICODE

typedef WCHAR TCHAR ,*PTCHAR, PTSTR;

typedef CONST WCHAR  *PCTSTR;

 

#else

 

typedef WCHAR TCHAR ,*PTCHAR, PTSTR;

typedef CONST WCHAR  *PCTSTR;

所以無論採用哪種字符標準,使用TCHAR都是編譯通過   TCHAR szBuffer[100] = _T("hello world!"); 故TCHAR稱爲通用類型。

此外對一些API函數也做了一些保持一致性的修改,如下:

#ifdef UNICODE

#define CreateWindowEx CreateWindowExW

 

#else

#define CreateWindowEx CreateWindowExA

 

#endif

 

 

五、

C運行庫中的Unicode函數和ANSI函數:

對於計算字符串長度的函數,C運行庫中,strlen是返回ANSI字符串的長度,與之對於的是wcslen,返回的是Unicode字符串的長度。

TChar.h文件中,定義了以下宏:

#ifdef UNICODE

#define _tcslen  wcslen

#else

#define _tcslen strlen

#endif

所以在代碼中不用管是否採用Unicode標準,可以直接調用_tcslen函數。

 

但是,任何修改字符串的函數都存在一個安全隱患,如果目標字符串的緩衝區不夠大,無法容下所生成的字符串,將會導致內存中的數據被破壞,例如strcpy和wcscpy,所以最好是用wcscat這樣指定緩衝區長度的字符串處理函數。相反的,像stlen和wcslen等不會修改傳入字符串的函數則是安全的。

目前微軟提供了一些新版本的字符串安全處理函數(tchar.h文件裏),即在函數名後面加_s ,例如_tcscpy_s,_tcscat_s,memcpy_s,memmove_s。它們的首要任務就是驗證傳給它們的參數值。例如指針不爲NULL,整數在有範圍內,緩衝區是否能容納結果大小等。

這裏我介紹一個宏_countof, 一些函數通常需要我傳入某個參數的緩衝區的字符數,而非字節數,所以我們就應該傳入_countof(szBuffer)而不是sizeof(szBuffer) 。在手動分配一塊內存的時候,要記住內存是以字節累分配的,這意味着我們必須調用malloc(nChars * sizeof(TCHAR))。

VC中有一個計算數組元素個數的MACRO

代碼如下:

#if !defined(_countof)
#if !defined(__cplusplus)
#define _countof(_Array) (sizeof(_Array) / sizeof(_Array[0]))
#else
extern "C++"
{
template <typename _CountofType, size_t _SizeOfArray>
char (*__countof_helper(UNALIGNED _CountofType (&_Array)[_SizeOfArray]))[_SizeOfArray];
#define _countof(_Array) sizeof(*__countof_helper(_Array))
}
#endif
#endif

C++版本的實現充分地利用了函數模板的參數自動推導機制,但我始終沒聊到函數指針也可以模板化,

 

六、寬字符與窄字符轉換

size_t mbstowcs(wchar_t *wcstr, const char *mbstr, size_t count)//由一個窄字符轉換到一個寬字符

size_t wcstombs(char *mbstr, const wchar_t *wcstr, size_t count)//由一個寬字符轉換到一個窄字符

發佈了24 篇原創文章 · 獲贊 1 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章