c++ vc编码踩坑总结

预备知识

参考这两个连接
从Emoji的限制到Unicode编码
带你玩转Visual Studio——带你理解多字节编码与Unicode码

vs studio c++ 项目目前只有两种编码格式,多字节和Unicode,默认都是多字节,这个有好处就是char兼容ascii 编码,缺点是当我们赋值其他国家语言时候就不能直接赋值了比如

// 多字节编码
void TestChar()
{
    char ch1 = 's';             // 正确
    cout << "ch1:" << ch1 << endl;
    char ch2 = '中';             // 错误,一个char不能完整存放一个汉字信息
    cout << "ch2:" << ch2 << endl;

    char str[4] = "中";          //前三个字节存放汉字'中',最后一个字节存放字符串结束符\0
    cout << "str:" << str << endl;
    //char str2[2] = "国";       // 错误:'str2' : array bounds overflow
    //cout << str2 << endl;
}

//  Unicode 编码
void TestWchar_t()
{
    wcout.imbue(locale("chs"));     // 将wcout的本地化语言设置为中文

    wchar_t wch1 = L's';            // 正确
    wcout << "wch1:" << wch1 << endl;
    wchar_t wch2 = L'中';            // 正确,一个汉字用一个wchar_t表示
    wcout << "wch2:" << wch2 << endl;
    
    wchar_t wstr[2] = L"中";         // 前两个字节(前一个wchar_t)存放汉字'中',最后两个字节(后一个wchar_t)存放字符串结束符\0
    wcout << "wstr:" << wstr << endl;
    wchar_t wstr2[3] = L"中国";
    wcout << "wstr2:" << wstr2 << endl;
}

多字节 处理编码

一般的项目选择多字节后,默认编码(我的是简体中文的vs studio 2013)是gb2312,可以从高级保存里面看到当前的文件的编码格式。


编码

这个时候我们可以调出我们的内存查看器查看我们的中国的编码是
d6 d0 b9 fa

GB2312

我们可以在这个网址在线编码看到如下结果



中国
Unicode 编码是 :
0x4E2D 0x56FD
utf8 编码是
e4 b8 ad e5 9b bd

我们可以根据这个函数来转为utf8 ,一般本地字符串这个不会导致乱码

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

但是通常我们会从数据库取数据,这个坑就比较多了,我用的是ado 来从sql server 获取nvarchar 的数据获取的结果如下:


可以看到我们获取的数据是Unicode的编码格式的,所以我们要直接转成utf8就行了不需要转成Unicode了。
这里有必要说下,ado 操作数据库有遍历结果集传入参数获取值,我目前发现使用结果集获取的是Unicode 编码,传入参数之前项目碰到过乱码了,所以建议使用结果集。

tips

这里怎么调出内存查看器和高级保存选项,大家可以自己搜索下,自己动手多学习学习下,我就不写入里面了。

附录:

Unicode 转utf8 的函数

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函数MultiByteToWideChar用于多字节编码字符串向宽字符串(即UTF-16 LE)的转码。它的第一个参数的常用值是CP_ACP和CP_OEMCP。
CP_ACP和CP_OEMCP,分别是指当前计算机上的Windows操作系统的Windows代码页与OEM代码页。对于东亚的简体中文、繁体中文、日文、韩文等Win操作系统语言环境,这两种代码页是同一个,如简体中文是代码页936即GB2312字符集,繁体中文是950即大五码字符集,韩文是949、日文是932。对于西方国家的拼音文字语言设置,两个代码页不同。典型的如English_US,其Windows代码页是1252、OEM代码页是437,还有第三个代码页ISO-8859-1又称Latin-1或“西欧语言”,是针对英语法语西语德语等西欧语言的扩展ASCII字符集。这三者(1252、437、8859-1)都是针对英语但并不相同。

编码转换规则
Unicode转UFT-8:设置WideCharToMultiByte的CodePage参数为CP_UTF8
Unicode转ANSI:设置WideCharToMultiByte的CodePage参数为CP_ACP
UTF-8转Unicode:设置MultiByteToWideChar的CodePage参数为CP_UTF8
ANSI转Unicode:设置MultiByteToWideChar的CodePage参数为CP_ACP
UTF-8转ANSI:先将UTF-8转换为Unicode,再将Unicode转换成ANSI 
ANSI转UTF-8:先将ANSI转换为Unciode,再将Unicode转换成ANSI。

ANSI 这里并不是严格的,是ANSI的拓展,指的是本地的编码,如中文就是GB2312


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,125评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,293评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,054评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,077评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,096评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,062评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,988评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,817评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,266评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,486评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,646评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,375评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,974评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,621评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,642评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,538评论 2 352