美文网首页
c++ vc编码踩坑总结

c++ vc编码踩坑总结

作者: YuWenHaiBo | 来源:发表于2019-07-26 16:41 被阅读0次

预备知识

参考这两个连接
从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


相关文章

  • c++ vc编码踩坑总结

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

  • AA C++学习参考

    网站 microsoft vc++cppreference.com中文版cplusplus.com某书c++并发编...

  • Coursera C++ Part A [Week1]基础概念与

    最近在学VC++,发现C++已经忘光了,码代码的过程中遇到了不少坑,重新从网上找个网课看一遍复习总结一下。 选择了...

  • vue 编码踩坑

    v-for $route VS $router 路由对象是 $route , 例如获取路由的名称 $rou...

  • VC Dimension

    VC Dimension 定义定义解释 M与VC Dimension VC Bound变形 总结 总结

  • VC++黑客编程收集的源码集合,只有你想不到的

    VC++黑客编程收集的源码集合 源码下载简介: 源码目录结构图: 如果你想学c++编程可以私信小编,发送“01”获...

  • 嵌入式面试高频考点(建议收藏)

    本篇参考网上及自身的面试经验,总结一些高频考察的Linux C/C++知识点,方便后续查阅总结。 一、C/C++编...

  • DRRG代码踩坑记录

    一、代码卡死问题: 训练一个epoch时,模型不能接着训练,只能通过Ctrl+C强制性暂停,直接卡死,并且输入...

  • 微软VC运行库 下载地址

    C++ 2008 ==> VC932位的VC9运行库下载:http://www.microsoft.com...

  • windows逆向3

    VC 程序内存和编译的一些特征C++ 构造函数C++ 成员函数C++ 析构函数C++ 全局对象的构造C++ 全局对...

网友评论

      本文标题:c++ vc编码踩坑总结

      本文链接:https://www.haomeiwen.com/subject/xfrdrctx.html