mbs字符串(char*)與Unicode字符串(wchar_t*)的轉換.md

一、C語言庫函數

(1)setlocale()

功能:配置地域化信息;在輸出Unicode字符串時會用到,在使用wcstombs函數時也會用到。下面英文描述中的用粗體字標出的函數都會用到該函數
頭文件:< locale.h>;
函數原型:

char *setlocale (int category, const char * locale);

函數參數:

  • category 表示對本地化的某項內容進行設置,可取如下值:

    • LC_ALL 包括下面的全部選項都要;
    • LC_COLLATE 配置字符串比較;
      The strcoll, _stricoll, wcscoll, _wcsicoll, strxfrm, _strncoll, _strnicoll, _wcsncoll, _wcsnicoll, and wcsxfrm functions.
    • C_CTYPE 配置字符類別及轉換,例如全變大寫 strtoupper();
      The character-handling functions (except isdigit, isxdigit, mbstowcs, and mbtowc, which are unaffected).
    • LC_MONETARY 配置金融貨幣;
      Monetary-formatting information returned by the localeconv function.
    • LC_NUMERIC 配置小數點後的位數;
      Decimal-point character for the formatted output routines (such as printf), for the data-conversion routines, and for the non-monetary formatting information returned by localeconv. In addition to the decimal-point character, LC_NUMERIC also sets the thousands separator and the grouping control string returned by localeconv.
    • LC_TIME 配置時間日期格式,與 strftime() 合用。
      The strftime and wcsftime functions.
  • locale 表示本地域代號:
    如果爲NULL,則返回當前的locale名稱(一般爲C);如果非空,則根據category和locale進行設置,如果成功,則返回新的locale名稱(地域名稱),如果失敗,則返回 NULL。

注意:可能剛開始對category參數有些不理解,category參數是指定全局變量locale會影響到的範圍,也就是說如果我指定了LC_COLLATE參數,那麼該函數的set只在字符串比較時會起作用

代碼示例:

int main()
{
   wchar_t wstr[] = L"Hello 中國";
   //locale傳 "" 空字符串用來返回當前環境的local名
   char* LocaleName = setlocale(LC_ALL, "");
   //locale傳 "chs" 表示設置locale爲簡體中文
   setlocale(LC_ALL, "chs");
   //輸出"Hello 中國",如果沒有setlocale配置區域信息的話wprintf是無法正常輸出中文字符的
   wprintf(wstr);
    //將區域信息設置回初始值
   if (0 == setlocale(LC_ALL, LocaleName))
   {
       printf("配置出錯\r\n");
       return 0;
   }
   return 0;
}

(2)wcstombs()

功能:將寬字符編碼字符串轉換成多字節編碼字符串
頭文件: < stdlib.h>
函數原型:

//普通版本
size_t wcstombs(
   char *mbstr,
   const wchar_t *wcstr,
   size_t count
);
//安全版本
errno_t  wcstombs_s(
   size_t * _PtNumOfCharConverted, 
   char * _Dst, 
   size_t _DstSizeInBytes, 
   const wchar_t * _Src, 
   size_t _MaxCountInBytes
);
//帶區域設置的安全版本
errno_t _wcstombs_s_l(
   size_t *pReturnValue,
   char *mbstr,
   size_t sizeInBytes,
   const wchar_t *wcstr,
   size_t count,
   _locale_t locale
);

函數參數
_PtNumOfCharConverted:指向轉換後的字符串的長度加上結束符(單位字節);
_Dst:指向轉換後的字符串首地址;
_DstSizeInBytes:目的地址最大字節空間(單位字節);
_Src:源寬字符串首地址;
_MaxCountInBytes:最多可存入多字節字符串緩衝最的字節數,用於裁剪轉換後的字符串。
返回值:成功返回0, 失敗則返回失敗代碼。

代碼示例:
沒有寫,和mbstowcs的差不多,寫在下面了。

(3)mbstowcs()

函數功能:將多字節編碼字符串轉換成寬字符編碼字符串
頭文件:< stdlib.h>
函數原型:

//普通版本
size_t mbstowcs(
   wchar_t *wcstr,
   const char *mbstr,
   size_t count
);
//安全版本
errno_t __cdecl mbstowcs_s(
   size_t * _PtNumOfCharConverted, 
   wchar_t * _DstBuf, 
   size_t _SizeInWords, 
   const char * _SrcBuf, 
   size_t _MaxCount 
);
//帶區域參數的安全版本
errno_t _mbstowcs_s_l(
   size_t *pReturnValue,
   wchar_t *wcstr,
   size_t sizeInWords,
   const char *mbstr,
   size_t count,
   _locale_t locale
);

參數說明:
_PtNumOfCharConverted:指向轉換後的字符串的長度加上結束符(單位wchar_t),;
_DstBuf:指向轉換後的字符串首地址;
_SizeInWords:目的地址最大字空間大小(單位wchar_t);
_SrcBuf:源多字節字符串首地址;
_MaxCount:最多可存入寬字符串緩衝中的字符個數,用於裁剪轉換後的寬字符串。

返回值:成功返回0, 失敗則返回失敗代碼。

代碼示例

  • 普通版本

    int main()
    {
    char str[] = "Hello 中國";
    //直接把寬度sizeof(str) * 2是有些內存資源浪費的,但也只能這樣了,MultiByteToWideChar是可以直接計算緩衝區大小的
    wchar_t wstr[sizeof(str) * 2];
    //使用mbstowcs轉換字符串
    mbstowcs(wstr,str,sizeof(str));
    //這裏使用C++中的輸出方式輸出
    wcout.imbue(locale("chs"));
    wcout << wstr << endl;
    return 0;
    }
  • 安全版本

    int main()
    {
    size_t convertedChars = 0;
    char str[] = "Hello 中國";
    //直接把寬度sizeof(str) * 2是有些內存資源浪費的,但也只能這樣了
    wchar_t wstr[sizeof(str) * 2];
    //設置區域信息爲簡體中文
    setlocale(LC_ALL, "chs");
    //使用mbstowcs轉換字符串
    mbstowcs_s(&convertedChars, wstr, str, sizeof(str));//convertedChars是_Out參數,用於記錄轉換成功的字符
    //這裏使用C++中的輸出方式輸出
    wcout.imbue(locale("chs"));
    wcout << wstr << endl;
    
    return 0;
    }
  • 帶區域參數的安全版本

    int main()
    {
    size_t convertedChars = 0;
    char str[] = "Hello 中國";
    //直接把寬度sizeof(str) * 2是有些內存資源浪費的,但也只能這樣了
    wchar_t wstr[sizeof(str) * 2];
    //使用_mbstowcs_s_l轉換字符串
    _mbstowcs_s_l(&convertedChars, wstr, sizeof(str)*2, str, sizeof(str), _create_locale(LC_ALL,"chs"));//convertedChars是_Out參數,用於記錄轉換成功的字符
    //這裏使用C++中的輸出方式輸出
    wcout.imbue(locale("chs"));
    wcout << wstr << endl;
    return 0;
    }

二、Windows函數

(1)WideCharToMultiByte()

函數功能:將寬字符串轉換成多字節字符串
頭文件:< windows.h>
函數原型:

int WINAPI WideCharToMultiByte(
    _In_ UINT CodePage,
    _In_ DWORD dwFlags,
    _In_NLS_string_(cchWideChar) LPCWCH lpWideCharStr,
    _In_ int cchWideChar,
    _Out_writes_bytes_to_opt_(cbMultiByte, return) LPSTR lpMultiByteStr,
    _In_ int cbMultiByte,
    _In_opt_ LPCCH lpDefaultChar,
    _Out_opt_ LPBOOL lpUsedDefaultChar
);

參數詳解:

  • CodePage:指定執行轉換的代碼頁字符集,可以爲操作系統已安裝或有效的任何代碼頁字符集,也可以指定其爲下面的任意一值:
    CP_ACP:ANSI代碼頁;
    CP_MACCP:Macintosh代碼頁;
    CP_OEMCP:OEM代碼頁;
    CP_SYMBOL:符號代碼頁;
    CP_THREAD_ACP:當前線程ANSI代碼頁;
    CP_UTF7:使用UTF-7轉換;
    CP_UTF8:使用UTF-8轉換。
    使用最多的就是CP_ACP和CP_UTF8;
  • dwFlags:指定如何處理沒有轉換成功的字符,也可以不設此參數(設置爲0),函數會運行的更快一些。對於UTF-8,dwflags必須爲0或者WC_ERR_INVALID_CHARS,否則函數都將失敗返回並設置錯誤碼ERROR_INVALID_FLAGS,可以調用GetLastError獲得;
  • lpWideCharStr:待轉換爲寬字符串;
  • cchWideChar:待轉換的寬字符串的長度(字符個數),-1表示轉換到字符串結尾;
  • lpMultiByteStr:轉換後目的字符串緩衝區;
  • cbMultiByte:目的字符串緩衝區大小(單位字節)。如果設置爲0,函數將返回所需緩衝區大小而忽略lpMultiByteStr;
  • lpDefaultChar:指向字符的指針,在指定編碼裏找不到相應字符時使用此字符作爲默認字符替代。如果爲NULL,則使用系統默認字符。使用dwFlags時不能使用此參數,否則報ERROR_INVLID_PARAMETER錯誤。
  • lpUsedDefaultChar:開關變量的指針,表明是否使用過默認字符。對於要求此參數爲NULL的dwflags而使用此參數,函數將失敗返回,並設置錯誤碼ERROR_INVLID_PARAMETER。lpDefaultChar和lpUsedDefaultChar都設爲NULL,函數會更快一些。

函數返回值:如果函數運行成功,並且cbMultiByte不爲零,返回值是由 lpMultiByteStr指向的緩衝區中寫入的字節數;如果函數運行成功,並且cbMultiByte爲零,返回值是接存放目的字符串緩衝區所必需的字節數。如果函數運行失敗,返回值爲零。若想獲得更多錯誤信息,請調用GetLastError函數。

代碼示例:將wstr中的字符轉換爲多字符集字符存儲到緩衝字符串str中

    WCHAR* wstr = L"Hollo 中國";
    char* str = NULL;
    //計算所需緩衝區大小,參數四-1表示轉換到字符串尾,參數六NULL表示計算並返回緩衝區大小,最後兩個參數傳NULL即可
    int lpMultiByteStr = WideCharToMultiByte(CP_ACP, NULL, wstr, -1,str,NULL,NULL,NULL);
    //動態申請緩衝區內存
    str = new char[lpMultiByteStr];
    //將轉換後的字符串寫進緩衝區,最後兩個參數傳NULL即可
    WideCharToMultiByte(CP_ACP, NULL, wstr, -1, str, lpMultiByteStr, NULL, NULL);
    //輸出測試
    setlocale(LC_ALL, str);
    cout << str << endl;
    //釋放緩衝區內存空間
    delete[] str;
    str = NULL;

(2)MultiByteToWideChar()

函數功能:多字節字符串到款字節字符串的轉換;
頭文件:< windows.h>
函數原型:

int WINAPI MultiByteToWideChar(
    _In_ UINT CodePage,
    _In_ DWORD dwFlags,
    _In_NLS_string_(cbMultiByte) LPCCH lpMultiByteStr,
    _In_ int cbMultiByte,
    _Out_writes_to_opt_(cchWideChar, return) LPWSTR lpWideCharStr,
    _In_ int cchWideChar
);

參數詳解:
- CodePage:同上;
- dwFlags:指定是否轉換成預製字符或合成的寬字符,是否使用象形文字替代控制字符,以及如何處理無效字符。對於UTF-8,dwflags必須爲0或者WC_ERR_INVALID_CHARS,否則函數都將失敗返回並設置錯誤碼ERROR_INVALID_FLAGS,可以調用GetLastError獲得;
- lpMultiByteStr:多字節字符串;
- cbMultiByte:待轉換的多字節字符串長度,-1表示轉換到字符串結尾;
- lpWideCharStr:存放轉換後的寬字符串緩衝;
- cchWideChar:寬字符串緩衝的大小(單位字符數)。

返回值:如果函數運行成功,並且cchWideChar不爲零,返回值是由 lpWideCharStr指向的緩衝區中寫入的字符數;如果函數運行成功,並且cchWideChar爲零,返回值是接存放目的字符串緩衝區所必需的字符數。如果函數運行失敗,返回值爲零。若想獲得更多錯誤信息,請調用GetLastError函數。

代碼示例:將str中的字符轉換爲多字符集字符存儲到緩衝字符串wstr中

    char str[] = "Hollo 中國";
    WCHAR* wstr = NULL;
    //計算所需緩衝區大小,參數四-1表示轉換到字符串尾,參數六NULL表示計算並返回緩衝區大小
    int lpMultiByteStr = MultiByteToWideChar(CP_ACP,NULL,str,-1,wstr,NULL);
    //動態申請緩衝區內存
    wstr = new wchar_t[lpMultiByteStr];
    //將轉換後的字符串寫進緩衝區
    MultiByteToWideChar(CP_ACP, NULL, str, -1, wstr, lpMultiByteStr);
    //輸出測試
    _wsetlocale(LC_ALL, L"chs"); //簡體中文的locale名稱爲:"chs"簡體中文的locale名稱爲:"chs"
    wprintf(wstr);
    //釋放緩衝區內存空間
    delete[] wstr;
    wstr = NULL;

參考資料
Dablelv的博客
http://blog.csdn.net/k346k346/article/details/50082705
白永輝的專欄
http://blog.csdn.net/xiaobai1593/article/details/7387889
感謝博主的好文!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章