utf-8編碼轉(zhuǎn)gbk(C語(yǔ)言實(shí)現(xiàn), 解決控制臺(tái)輸出utf-8亂碼問題)

今天在windows控制臺(tái)上打印utf-8字符時(shí)出現(xiàn)了亂碼,然后就折騰了一下發(fā)現(xiàn)在簡(jiǎn)體中文版上的windows默認(rèn)的代碼頁(yè)是936(gbk編碼),在控制臺(tái)上輸入chcp 65001解決之(65001是UTF-8代碼頁(yè)編號(hào)),但是我這么愛鉆研(瞎折騰)怎么可能就這么完事了呢,就嘗試了下用C語(yǔ)言實(shí)現(xiàn)utf-8轉(zhuǎn)化成gbk編碼(還順便學(xué)習(xí)了下幾種編碼),下面是解決方法。

嗯。。還有我學(xué)習(xí)時(shí)看的一個(gè)資料,介紹編碼知識(shí)的

http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html

解決方法

1.使用代碼更改活動(dòng)代碼頁(yè)

system("chcp 65001");

也可以使用windows的一個(gè)API(設(shè)置輸出代碼頁(yè)),效果一樣

SetConsoleOutputCP(65001);

還有另外一個(gè)API是SetConsoleCP(),這個(gè)API設(shè)置的是輸入代碼頁(yè),在輸出時(shí)并不起作用

C語(yǔ)言標(biāo)準(zhǔn)里面還提供了一個(gè)函數(shù)來(lái)設(shè)置代碼頁(yè)Setlocale(),不過沒有測(cè)試過

2.將utf-8轉(zhuǎn)換成gbk編碼

原理是利用windows的兩個(gè)API,將UTF-8轉(zhuǎn)成unicode編碼,再轉(zhuǎn)成gbk編碼

下面是對(duì)兩個(gè)函數(shù)的介紹

函數(shù)原型

int MultiByteToWideChar(

UINT CodePage,

DWORD dwFlags,

LPCSTR lpMultiByteStr,

int cchMultiByte,

LPWSTR lpWideCharStr,

int cchWideChar);

函數(shù)功能?

該函數(shù)映射一個(gè)字符串到一個(gè)寬字符(unicode)的字符串。由該函數(shù)映射的字符串沒必要是多字節(jié)字符組。

參數(shù)

CodePage:指定執(zhí)行轉(zhuǎn)換的代碼頁(yè),這個(gè)參數(shù)可以為系統(tǒng)已安裝或有效的任何代碼頁(yè)所給定的值。我們用到的是下面兩個(gè)值(當(dāng)然你也可以指定別的值):

CP_ACP:ANSI代碼頁(yè)(簡(jiǎn)體中文Windows操作系統(tǒng)中,ANSI 編碼代表 GBK 編碼)

CP_UTF8:使用UTF-8轉(zhuǎn)換

dwFlags: 指定如何處理沒有轉(zhuǎn)換的字符,但不設(shè)此參數(shù)函數(shù)會(huì)運(yùn)行的更快一些,我都是把它設(shè)為0。 可設(shè)的值如下表所示:

WC_NO_BEST_FIT_CHARS

把不能直接轉(zhuǎn)換成相應(yīng)多字節(jié)字符的Unicode字符轉(zhuǎn)換成lpDefaultChar指定的默認(rèn)字符。也就是說,如果把Unicode轉(zhuǎn)換成多字節(jié)字符,然后再轉(zhuǎn)換回來(lái),你并不一定得到相同的Unicode字符,因?yàn)檫@期間可能使用了默認(rèn)字符。此選項(xiàng)可以單獨(dú)使用,也可以和其他選項(xiàng)一起使用。

WC_COMPOSITECHECK

把合成字符轉(zhuǎn)換成預(yù)制的字符。它可以與后三個(gè)選項(xiàng)中的任何一個(gè)組合使用,如果沒有與他們中的任何一個(gè)組合,則與選項(xiàng)WC_SEPCHARS相同。

WC_ERR_INVALID_CHARS

此選項(xiàng)會(huì)致使函數(shù)遇到無(wú)效字符時(shí)失敗返回,并且GetLastError會(huì)返回錯(cuò)誤碼ERROR_NO_UNICODE_TRANSLATION。否則函數(shù)會(huì)自動(dòng)丟棄非法字符。此選項(xiàng)只能用于UTF8。

WC_DISCARDNS? ?

轉(zhuǎn)換時(shí)丟棄不占空間的字符,與WC_COMPOSITECHECK 一起使用

WC_SEPCHARS

轉(zhuǎn)換時(shí)產(chǎn)生單獨(dú)的字符,此是默認(rèn)轉(zhuǎn)換選項(xiàng),WC_COMPOSITECHECK一起使用

WC_DEFAULTCHAR

轉(zhuǎn)換時(shí)使用默認(rèn)字符代替例外的字符,(最常見的如’?’),與WC_COMPOSITECHECK一起使用。

對(duì)于下列代碼頁(yè),dwFlags必須為0,否則函數(shù)返回錯(cuò)誤碼ERROR_INVALID_FLAGS。 50220 50221 50222 50225 50227 50229 52936 54936 57002到57011 65000(UTF7) 42(Symbol)

對(duì)于UTF8,dwFlags必須為0或WC_ERR_INVALID_CHARS,否則函數(shù)都將失敗返回并設(shè)置錯(cuò)誤碼ERROR_INVALID_FLAGS,你可以調(diào)用GetLastError獲得。


lpMultiByteStr:指向?qū)⒈晦D(zhuǎn)換字符串的字符。

cchMultiByte:指定由參數(shù)lpMultiByteStr指向的字符串中字節(jié)的個(gè)數(shù)。如果這個(gè)值為-1,字符串將被設(shè)定為以NULL為結(jié)束符的字符串,并且自動(dòng)計(jì)算長(zhǎng)度。

lpWideCharStr:指向接收被轉(zhuǎn)換字符串的緩沖區(qū)。

cchWideChar:指定由參數(shù)lpWideCharStr指向的緩沖區(qū)的字節(jié)個(gè)數(shù)。若此值為零,函數(shù)返回緩沖區(qū)所必需的寬字符數(shù),在這種情況下,lpWideCharStr中的緩沖區(qū)不被使用。

返回值:如果函數(shù)運(yùn)行成功,并且cchWideChar不為零,返回值是由lpWideCharStr指向的緩沖區(qū)中寫入的寬字符數(shù);如果函數(shù)運(yùn)行成功,并且cchMultiByte為零,返回值是接收到待轉(zhuǎn)換字符串的緩沖區(qū)所需求的寬字符數(shù)大小。如果函數(shù)運(yùn)行失敗,返回值為零。

函數(shù)原型

int WideCharToMultiByte(

UINT CodePage,

DWORD dwFlags,

LPCWSTR lpWideCharStr,

int cchWideChar,

LPSTR lpMultiByteStr,

int cbMultiByte,

LPCSTR lpDefaultChar,

LPBOOL lpUsedDefaultChar);

函數(shù)功能?

此函數(shù)把寬字符串轉(zhuǎn)換成指定的新的字符串,如ANSI,UTF8等,新字符串不必是多字節(jié)字符集。?

參數(shù)

lpWideCharStr : 待轉(zhuǎn)換的寬字符串。

cchWideChar : 待轉(zhuǎn)換寬字符串的長(zhǎng)度,-1表示轉(zhuǎn)換到字符串結(jié)尾。

lpMultiByteStr : 接收轉(zhuǎn)換后輸出新串的緩沖區(qū)。

cbMultiByte :輸出緩沖區(qū)大小,如果為0,lpMultiByteStr將被忽略,函數(shù)將返回所需緩沖區(qū)大小而不使用lpMultiByteStr。

lpDefaultChar : 指向字符的指針, 在指定編碼里找不到相應(yīng)字符時(shí)使用此字符作為默認(rèn)字符代替。如果為NULL則使用系統(tǒng)默認(rèn)字符。對(duì)于要求此參數(shù)為NULL的dwFlags而使用此參數(shù),函數(shù)將失敗返回并設(shè)置錯(cuò)誤碼ERROR_INVALID_PARAMETER。

lpUsedDefaultChar :開關(guān)變量的指針,用以表明是否使用過默認(rèn)字符。對(duì)于要求此參數(shù)為NULL的dwFlags而使用此參數(shù),函數(shù)將失敗返回并設(shè)置錯(cuò)誤碼ERROR_INVALID_PARAMETER。lpDefaultChar和lpUsedDefaultChar都設(shè)為NULL,函數(shù)會(huì)更快一些。

返回值 :如果函數(shù)成功,且cbMultiByte非0,返回寫入lpMultiByteStr的字節(jié)數(shù)(包括字符串結(jié)尾的null);cbMultiByte為0,則返回轉(zhuǎn)換所需字節(jié)數(shù)。函數(shù)失敗,返回0。


下面是簡(jiǎn)單的函數(shù)實(shí)現(xiàn)

void utf8ToGbk(char *utf8String, char *gbkString)

{

wchar_t *unicodeStr = NULL;

int nRetLen = 0;

nRetLen = MultiByteToWideChar(CP_UTF8, 0, utf8String, -1, NULL, 0);

//求需求的寬字符數(shù)大小

unicodeStr = (wchar_t *)malloc(nRetLen * sizeof(wchar_t));

nRetLen = MultiByteToWideChar(CP_UTF8, 0, utf8String, -1, unicodeStr, nRetLen);

//將utf-8編碼轉(zhuǎn)換成unicode編碼

nRetLen = WideCharToMultiByte(CP_ACP, 0, unicodeStr, -1, NULL, 0, NULL, 0);

//求轉(zhuǎn)換所需字節(jié)數(shù)

nRetLen = WideCharToMultiByte(CP_ACP, 0, unicodeStr, -1, gbkString, nRetLen, NULL, 0);

//unicode編碼轉(zhuǎn)換成gbk編碼

free(unicodeStr);

}



第三篇文章哈哈哈哈



人生是一場(chǎng)規(guī)模龐大的摸彩游戲,只有中獎(jiǎng)的彩票展現(xiàn)在我們眼前?!都埮频拿孛堋?/p>



給我點(diǎn)十個(gè)贊我就買杯可樂慶祝下

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 第2章 基本語(yǔ)法 2.1 概述 基本句法和變量 語(yǔ)句 JavaScript程序的執(zhí)行單位為行(line),也就是一...
    悟名先生閱讀 4,540評(píng)論 0 13
  • 編碼問題一直困擾著開發(fā)人員,尤其在 Java 中更加明顯,因?yàn)?Java 是跨平臺(tái)語(yǔ)言,不同平臺(tái)之間編碼之間的切換...
    x360閱讀 2,578評(píng)論 1 20
  • 第5章 引用類型(返回首頁(yè)) 本章內(nèi)容 使用對(duì)象 創(chuàng)建并操作數(shù)組 理解基本的JavaScript類型 使用基本類型...
    大學(xué)一百閱讀 3,674評(píng)論 0 4
  • 秋雨曉輕寒,秋暮雙歸燕。 秋葉飄香砌,秋思未成眠。
    騏鏞如一閱讀 242評(píng)論 0 1
  • 文件架構(gòu) 詳細(xì)說明
    brightranger閱讀 267評(píng)論 0 0

友情鏈接更多精彩內(nèi)容