c++ 中字符串编码 转码

转自:https://my.oschina.net/shelllife/blog/1827897

C/C++语言中的字符类型

存在两种表示字符的基本类型:

  • char:一个字节8bit表示,最多表示256个字符,表示和用来处理ASCII字符集,国际通用
  • wchar_t:多字节字符表示,典型2个字节或者4个字节,如GNU libc中为4B,可以表示更多的字符,满足国际化应用开发的需求,实现标准

在开发中ASCII编码字符都是用char来表示,可以转换成wchar_t表示;wchar_t类型与Unicode编码是完全独立的概念,不过在实现上Unicode编码一般用wchar_t来表示实现而已,但wchar_t字符并不一定就是Unicode编码字符。

对应两种字符类型存在两种字符串类型(C++):

  • string: char字符列表或者是字节列表(bytes)
  • wstring: wchar_t字符列表或者是宽子节列表

对应两种字符类型的输出函数流对象有:

  • sprintf/wsprintf: 分别对应char与wchar_t
  • cout/wcout:分别对应string与wstring
  • stringstream/wstringstream: 分别对应string与wstring

字符串常量

C++11标准中增加了一些表示字符串常量的标识,如下有:

  • L"您好!": wstring字符串常量,使用文件保存编码方式字符集
  • R"(您 好 \n)": 原始字符串常量(字节数组),保留所有的字符
  • u8"您好!": string字符串常量(字节数组),使用UTF8进行编码保存

字符集及编码

已知有很多的字符集,比如:ASCII,UTF8,GBK,GB2312,UTF16,UTF32,UNICODE,Latin等等。常用中文字符集编码有:

  • UTF8:又分为带签名和不带签名两种,Windows代码页为65001,VS中应该选择【UTF8-带签名】的格式
  • GBK/GB2312:Windows代码页为936
  • GB18030: Windows代码页为54936

小技巧:修改Windows系统中cmd命令行窗口的显示字符集,默认字符集为OS字符集,如GBK-936。如果希望显示UTF8字符,则可以修改:chcp 65001.

在VS项目的调试命令窗口中无法手动修改,可以通过system函数来修改:

system("C:\\Windows\\system32\\chcp 65001");// 修改终端字符集为UTF8

源文件的编码保存选项

可以将源文件保存成不同的编码方式,如果文件中有中文,则必须选择可以对中文进行编码的字符集,如UTF8,GBK,GB2312等,否认可能会出现莫名其妙的编译错误,因为文件中存在无法识别的字符内容。

在Visual Studio中,选中文件后该设置在:【文件 - 高级保存选项】中。

C++11中GBK/UTF/wchar_t之间的编码处理转换

在处理中文时,不同的应用场景下总是无法避免进行GBK和UTF8之间的相互转换,C++11标识提供了<locale>和<codecvt>机制和工具来简化处理。

借助其中的std::wstring_convert和std::codecvt_utf8模板,通过wchar_t类型为中介,可以快速地实现转换,基本代码如下:

/*
    转换GBK编码的中文到UTF8编码:GBK - WChar - UTF8两次转换
*/
//GBK在linux下的locale名可能是"zh_CN.GBK" 
const char* GBK_LOCALE_NAME = ".936"; //GBK在windows下的locale name 
std::wstring_convert<std::codecvt_byname<wchar_t, char, mbstate_t>> Conver_GBK(new codecvt_byname<wchar_t, char, mbstate_t>(GBK_LOCALE_NAME)); //GBK - wchar_t
std::wstring _wname = Conver_GBK.from_bytes(data.Name); // 输入为char*的字符串表示或者数组,输出为wstring
std::wstring _waddr = Conver_GBK.from_bytes(data.Address);// 输入为char*的字符串表示或者数组,输出为wstring
std::wstring _wdept = Conver_GBK.from_bytes(data.GrantDept);// 输入为char*的字符串表示或者数组,输出为wstring

wcout << "Name: " << _wname << ",addr:" << _waddr << ",dept:" << _wdept << endl;

// 将wstring转化为UTF8编码的字节数组string表示
std::wstring_convert<std::codecvt_utf8<wchar_t>> conv;
string _name = conv.to_bytes(_wname);// 输入为wstring字符串
string _addr = conv.to_bytes(_waddr);
string _dept = conv.to_bytes(_wdept);

// 将UTF8字符串转换为GBK字符编码表示string字节数组
std::string _name = Conver_GBK.to_bytes(conv.from_bytes(_name)); // 先转换成wstring,然后再转换成GBK的string
std::string _addr = Conver_GBK.to_bytes(conv.from_bytes(_addr)); // 先转换成wstring,然后再转换成GBK的string
posted @ 2020-09-25 10:25  Bigben  阅读(8110)  评论(0编辑  收藏  举报