1. 程式人生 > 其它 >c++中wstring 和 string的轉換 (轉載)

c++中wstring 和 string的轉換 (轉載)

原文地址https://www.cnblogs.com/bookdrip/p/9987099.html

一、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;
}