c++ vc編碼踩坑總結(jié)

預(yù)備知識(shí)

參考這兩個(gè)連接
從Emoji的限制到Unicode編碼
帶你玩轉(zhuǎn)Visual Studio——帶你理解多字節(jié)編碼與Unicode碼

vs studio c++ 項(xiàng)目目前只有兩種編碼格式,多字節(jié)和Unicode,默認(rèn)都是多字節(jié)袭景,這個(gè)有好處就是char兼容ascii 編碼汗菜,缺點(diǎn)是當(dāng)我們賦值其他國家語言時(shí)候就不能直接賦值了比如

// 多字節(jié)編碼
void TestChar()
{
    char ch1 = 's';             // 正確
    cout << "ch1:" << ch1 << endl;
    char ch2 = '中';             // 錯(cuò)誤,一個(gè)char不能完整存放一個(gè)漢字信息
    cout << "ch2:" << ch2 << endl;

    char str[4] = "中";          //前三個(gè)字節(jié)存放漢字'中',最后一個(gè)字節(jié)存放字符串結(jié)束符\0
    cout << "str:" << str << endl;
    //char str2[2] = "國";       // 錯(cuò)誤:'str2' : array bounds overflow
    //cout << str2 << endl;
}

//  Unicode 編碼
void TestWchar_t()
{
    wcout.imbue(locale("chs"));     // 將wcout的本地化語言設(shè)置為中文

    wchar_t wch1 = L's';            // 正確
    wcout << "wch1:" << wch1 << endl;
    wchar_t wch2 = L'中';            // 正確,一個(gè)漢字用一個(gè)wchar_t表示
    wcout << "wch2:" << wch2 << endl;
    
    wchar_t wstr[2] = L"中";         // 前兩個(gè)字節(jié)(前一個(gè)wchar_t)存放漢字'中',最后兩個(gè)字節(jié)(后一個(gè)wchar_t)存放字符串結(jié)束符\0
    wcout << "wstr:" << wstr << endl;
    wchar_t wstr2[3] = L"中國";
    wcout << "wstr2:" << wstr2 << endl;
}

多字節(jié) 處理編碼

一般的項(xiàng)目選擇多字節(jié)后地淀,默認(rèn)編碼(我的是簡(jiǎn)體中文的vs studio 2013)是gb2312,可以從高級(jí)保存里面看到當(dāng)前的文件的編碼格式梧疲。


編碼

這個(gè)時(shí)候我們可以調(diào)出我們的內(nèi)存查看器查看我們的中國的編碼是
d6 d0 b9 fa

GB2312

我們可以在這個(gè)網(wǎng)址在線編碼看到如下結(jié)果



中國
Unicode 編碼是 :
0x4E2D 0x56FD
utf8 編碼是
e4 b8 ad e5 9b bd

我們可以根據(jù)這個(gè)函數(shù)來轉(zhuǎn)為utf8 ,一般本地字符串這個(gè)不會(huì)導(dǎo)致亂碼

string GBKToUTF8(const char* strGBK)
{
    int len = MultiByteToWideChar(CP_ACP, 0, strGBK, -1, NULL, 0);
    wchar_t* wstr = new wchar_t[len + 1];
    memset(wstr, 0, len + 1);
    MultiByteToWideChar(CP_ACP, 0, strGBK, -1, wstr, len);
    len = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL);
    char* str = new char[len + 1];
    memset(str, 0, len + 1);
    WideCharToMultiByte(CP_UTF8, 0, wstr, -1, str, len, NULL, NULL);
    string strTemp = str;
    if (wstr) delete[] wstr;
    if (str) delete[] str;
    return strTemp;
}

但是通常我們會(huì)從數(shù)據(jù)庫取數(shù)據(jù)擦耀,這個(gè)坑就比較多了饼酿,我用的是ado 來從sql server 獲取nvarchar 的數(shù)據(jù)獲取的結(jié)果如下:


可以看到我們獲取的數(shù)據(jù)是Unicode的編碼格式的榕酒,所以我們要直接轉(zhuǎn)成utf8就行了不需要轉(zhuǎn)成Unicode了。
這里有必要說下故俐,ado 操作數(shù)據(jù)庫有遍歷結(jié)果集傳入?yún)?shù)獲取值想鹰,我目前發(fā)現(xiàn)使用結(jié)果集獲取的是Unicode 編碼,傳入?yún)?shù)之前項(xiàng)目碰到過亂碼了药版,所以建議使用結(jié)果集辑舷。

tips

這里怎么調(diào)出內(nèi)存查看器和高級(jí)保存選項(xiàng),大家可以自己搜索下槽片,自己動(dòng)手多學(xué)習(xí)學(xué)習(xí)下何缓,我就不寫入里面了。

附錄:

Unicode 轉(zhuǎn)utf8 的函數(shù)

bool Unicode2UTF(vector<char> &Dest, wchar_t *szSrc)
{
    int iTextLen = wcslen(szSrc);
    if (iTextLen == 0)
    {
        return false;
    }
    iTextLen = WideCharToMultiByte(CP_UTF8,
        0,
        (LPWSTR)szSrc,
        -1,
        NULL,
        0,
        NULL,
        NULL);
    if (iTextLen == 0)
        return false;
    Dest.resize(iTextLen);
    ::WideCharToMultiByte(CP_UTF8,
        0,
        (LPWSTR)szSrc,
        -1,
        &*Dest.begin(),
        iTextLen,
        NULL,
        NULL);

    return true;

}


Windows API函數(shù)MultiByteToWideChar用于多字節(jié)編碼字符串向?qū)捵址碪TF-16 LE)的轉(zhuǎn)碼还栓。它的第一個(gè)參數(shù)的常用值是CP_ACP和CP_OEMCP碌廓。
CP_ACP和CP_OEMCP,分別是指當(dāng)前計(jì)算機(jī)上的Windows操作系統(tǒng)的Windows代碼頁與OEM代碼頁剩盒。對(duì)于東亞的簡(jiǎn)體中文谷婆、繁體中文、日文、韓文等Win操作系統(tǒng)語言環(huán)境波材,這兩種代碼頁是同一個(gè)股淡,如簡(jiǎn)體中文是代碼頁936即GB2312字符集,繁體中文是950即大五碼字符集廷区,韓文是949唯灵、日文是932。對(duì)于西方國家的拼音文字語言設(shè)置隙轻,兩個(gè)代碼頁不同埠帕。典型的如English_US,其Windows代碼頁是1252玖绿、OEM代碼頁是437敛瓷,還有第三個(gè)代碼頁ISO-8859-1又稱Latin-1或“西歐語言”,是針對(duì)英語法語西語德語等西歐語言的擴(kuò)展ASCII字符集斑匪。這三者(1252呐籽、437、8859-1)都是針對(duì)英語但并不相同蚀瘸。

編碼轉(zhuǎn)換規(guī)則
Unicode轉(zhuǎn)UFT-8:設(shè)置WideCharToMultiByte的CodePage參數(shù)為CP_UTF8
Unicode轉(zhuǎn)ANSI:設(shè)置WideCharToMultiByte的CodePage參數(shù)為CP_ACP
UTF-8轉(zhuǎn)Unicode:設(shè)置MultiByteToWideChar的CodePage參數(shù)為CP_UTF8
ANSI轉(zhuǎn)Unicode:設(shè)置MultiByteToWideChar的CodePage參數(shù)為CP_ACP
UTF-8轉(zhuǎn)ANSI:先將UTF-8轉(zhuǎn)換為Unicode狡蝶,再將Unicode轉(zhuǎn)換成ANSI 
ANSI轉(zhuǎn)UTF-8:先將ANSI轉(zhuǎn)換為Unciode,再將Unicode轉(zhuǎn)換成ANSI贮勃。

ANSI 這里并不是嚴(yán)格的贪惹,是ANSI的拓展,指的是本地的編碼寂嘉,如中文就是GB2312


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末奏瞬,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子泉孩,更是在濱河造成了極大的恐慌硼端,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,252評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件棵譬,死亡現(xiàn)場(chǎng)離奇詭異显蝌,居然都是意外死亡预伺,警方通過查閱死者的電腦和手機(jī)订咸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來酬诀,“玉大人脏嚷,你說我怎么就攤上這事÷饔” “怎么了父叙?”我有些...
    開封第一講書人閱讀 168,814評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我趾唱,道長涌乳,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,869評(píng)論 1 299
  • 正文 為了忘掉前任甜癞,我火速辦了婚禮夕晓,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘悠咱。我一直安慰自己蒸辆,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,888評(píng)論 6 398
  • 文/花漫 我一把揭開白布析既。 她就那樣靜靜地躺著躬贡,像睡著了一般。 火紅的嫁衣襯著肌膚如雪眼坏。 梳的紋絲不亂的頭發(fā)上拂玻,一...
    開封第一講書人閱讀 52,475評(píng)論 1 312
  • 那天,我揣著相機(jī)與錄音宰译,去河邊找鬼纺讲。 笑死,一個(gè)胖子當(dāng)著我的面吹牛囤屹,可吹牛的內(nèi)容都是我干的熬甚。 我是一名探鬼主播,決...
    沈念sama閱讀 41,010評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼肋坚,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼乡括!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起智厌,我...
    開封第一講書人閱讀 39,924評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤诲泌,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后铣鹏,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體敷扫,經(jīng)...
    沈念sama閱讀 46,469評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,552評(píng)論 3 342
  • 正文 我和宋清朗相戀三年诚卸,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了葵第。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,680評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡合溺,死狀恐怖卒密,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情棠赛,我是刑警寧澤哮奇,帶...
    沈念sama閱讀 36,362評(píng)論 5 351
  • 正文 年R本政府宣布膛腐,位于F島的核電站,受9級(jí)特大地震影響鼎俘,放射性物質(zhì)發(fā)生泄漏哲身。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,037評(píng)論 3 335
  • 文/蒙蒙 一贸伐、第九天 我趴在偏房一處隱蔽的房頂上張望律罢。 院中可真熱鬧,春花似錦棍丐、人聲如沸误辑。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,519評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽巾钉。三九已至,卻和暖如春秘案,著一層夾襖步出監(jiān)牢的瞬間砰苍,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,621評(píng)論 1 274
  • 我被黑心中介騙來泰國打工阱高, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留赚导,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,099評(píng)論 3 378
  • 正文 我出身青樓赤惊,卻偏偏與公主長得像吼旧,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子未舟,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,691評(píng)論 2 361