一、wchar_t和char的基礎知識
1.C程序中使用的char類型,是占用一個字節,一共可以表示256個字符。而在32位系統中,char*是占用四個字節的,因為一個指針變量占用的存儲空間為4個字節。char類型的編碼規則一般為ASCII編碼。我在此處測試了一下再GCC中char[]是不可以存儲中文字符的(可能是我的編譯器沒有和編輯器的編碼方式不一樣,導致出來的結果是亂碼的中文),但是在vs中,似乎使用某些優化,char是可以用來存儲中文字符的。但是他們都是顯示出文字來的,ASCII編碼中沒有漢字,但是還是顯示出來了,這本身存在一些我們不知道的操作(這個內容需要自己來深究)。
在嘗試了修改了編碼問題后,GCC編譯器也可以實現中文的輸入了。(待續)
此時,對於這個問題我已經找到了我的答案
普通的char類型是一個正數,是從0-127個編碼,而輸入中文的字符的值第一個字節都是負數(很難受,好像還是不對),可能是通過數字的符號來判定改符號是一個字節還是兩個字節的。因此判定char的編碼規則應該不只是Ascii一種。
2.wchar_t在C程序中占用的字節為2個字節,相當於一個無符號短整型。其長度是可變的,根據運行的平台而定,可以是2個字節或者是4個字節。在win32 MSVC環境下,C庫中wchar_t的長度為2個字節
typedefine unsigned short wchar_t;/* 16bits*/
wchar_t采用的是unicode編碼,unicode的編碼是固定的,但是因為其需要2到4個字節,它的存儲方法不盡相同。所以會產生不同版本的unicode。
unicode 的一種實現方式 UTF-8。
參見鏈接https://www.cnblogs.com/kingstarspe/p/ASCII.html
UTF-8的編碼規則很簡單,只有二條:
1)對於單字節的符號,字節的第一位設為0,后面7位為這個符號的unicode碼。因此對於英語字母,UTF-8編碼和ASCII碼是相同的。
2)對於n字節的符號(n>1),第一個字節的前n位都設為1,第n+1位設為0,后面字節的前兩位一律設為10。剩下的沒有提及的二進制位,全部為這個符號的unicode碼。
(未完待續)
wchar_t*與char*的轉換
經過了上面的邏輯討論之后我們可以發現,其實char和wchar_t的轉換過程就是一個編碼轉化的過程,需要大量的判斷語句來實現,其原理大概也就是根據字節的信號來判斷字符需要的字節數。下面僅提高用於編程的模板。
這是在window下的方法,需要添加<windows.h>頭文件
//將單字節char*轉化為寬字節wchar_t* wchar_t* AnsiToUnicode( const char* szStr ) { int nLen = MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, szStr, -1, NULL, 0 ); if (nLen == 0) { return NULL; } wchar_t* pResult = new wchar_t[nLen]; MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, szStr, -1, pResult, nLen ); return pResult; } //將寬字節wchar_t*轉化為單字節char* char* UnicodeToAnsi( const wchar_t* szStr ) { int nLen = WideCharToMultiByte( CP_ACP, 0, szStr, -1, NULL, 0, NULL, NULL ); if (nLen == 0) { return NULL; } char* pResult = new char[nLen]; WideCharToMultiByte( CP_ACP, 0, szStr, -1, pResult, nLen, NULL, NULL ); return pResult; }
下面這段代碼實現的是string和wstring的轉換,可能在實際中運用的比較多,(只有在C++中才有string類型哦,純C中只能使用char*或者是char []),稍作修改之后就可以成為char*和wchar_t直接的轉換函數了。該函數用到的頭文件是C中的<string>文件。
//wstring=>string std::string WString2String(const std::wstring& ws) { std::string strLocale = setlocale(LC_ALL, ""); const wchar_t* wchSrc = ws.c_str(); size_t nDestSize = wcstombs(NULL, wchSrc, 0) + 1; char *chDest = new char[nDestSize]; memset(chDest, 0, nDestSize); wcstombs(chDest, wchSrc, nDestSize); std::string strResult = chDest; delete[]chDest; setlocale(LC_ALL, strLocale.c_str()); return strResult; } // string => wstring std::wstring String2WString(const std::string& s) { std::string strLocale = setlocale(LC_ALL, ""); const char* chSrc = s.c_str(); size_t nDestSize = mbstowcs(NULL, chSrc, 0) + 1; wchar_t* wchDest = new wchar_t[nDestSize]; wmemset(wchDest, 0, nDestSize); mbstowcs(wchDest, chSrc, nDestSize); std::wstring wstrResult = wchDest; delete[]wchDest; setlocale(LC_ALL, strLocale.c_str()); return wstrResult; }
(以后不遇見問題,可能就不會再深究了,再見了)
)