计算机技术论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

  • 欢迎访问 计算机技术论坛-电脑迷与初学者的家园!由于论坛管理严格,新注册会员可能遇到各种问题,无法解决的请发邮件 admin@jsjbbs.cn
查看: 843|回复: 0

C++中字符编码的转换

[复制链接]
发表于 2021-4-6 07:19:36 | 显示全部楼层 |阅读模式
#111723#作者:FlushHip
在处置西方言语(中日韩)时,常常会碰到种种编码成绩,并且被这类成绩搞的晕头转向。到网上查材料,看的也是一头雾水,最后常常是误打误撞的把成绩处理了,本人依然稀里胡涂。
这篇文章先容了怎样在最罕见的编码方法(Unicode, UTF-8, ANSI)之间停止转换,联合代码实例,清楚明白,便利读者懂得,例子也能够直接拿来应用。本文推举给常常对笔墨字符串停止处置的顺序员浏览,使其控制字符转换的一些基础方式。
注释
C++++的名目,字符编码是一个大坑,差别平台之间的编码常常纷歧样,假如差别编码格局用一套字符读取格局读取就会呈现乱码。因而,个别都是转化成UTF-8这类平台通用,且支撑性很好的编码格局。
Unicode、UTF-8的观点不做过量说明,这里说一下ANSI,我第一次看到这个名词,我当作了ASCII。被Mentor狠批一顿。
ANSI是一种字符代码,为使盘算机支撑更多言语,平日应用 0x00 ~ 0x7F范畴的1 个字节来表现 1 个英笔墨符。超越此范畴应用0x80~0xFFFF来编码,即扩大的ASCII编码。
差别的国度和地域制订了差别尺度,由此发生了 GB2312、GBK、GB18030、Big5、Shift_JIS 等各自的编码尺度。这些应用多个字节来代表一个字符的种种汉字延长编码方法,称为 ANSI 编码。在简体中文Windows操纵体系,ANSI 编码代表 GBK 编码;在繁体中文Windows操纵体系,ANSI编码代表Big5;在日文Windows操纵体系,ANSI 编码代表 Shift_JIS 编码。
以上内容摘自百度百科,能够看出,ANSI和ASCII仍是有关联的。ANSI也叫当地码。
咱们要做到能在Unicode、UTF-8、ANSI这三种编码格局中自在转换。以下图所示:

在C++中,要怎样做呢?固然是用尺度库的货色啦,C++11对国际化尺度做得仍是能够的,供给了这些接口,正如图中虚线所示,尺度库没有供给UTF-8到ANSI的相互转化接口,然而咱们能够本人封转接口,借用这条路(UTF-8 《=》 Unicode 《=》 ANSI)来实现。
因而,接上去就聊聊UTF8 《=》 Unicode和Unicode 《=》 ANSI。
UTF8 《=》 Unicode
先看代码:
std::string UnicodeToUTF8(const std::wstring & wstr){ std::string ret; try { std::wstring_convert《 std::codecvt_utf8《wchar_t》 》 wcv; ret = wcv.to_bytes(wstr); } catch (const std::exception & e) { std::cerr 《《 e.what() 《《 std::endl; } return ret;}std::wstring UTF8ToUnicode(const std::string & str){ std::wstring ret; try { std::wstring_convert《 std::codecvt_utf8《wchar_t》 》 wcv; ret = wcv.from_bytes(str); } catch (const std::exception & e) { std::cerr 《《 e.what() 《《 std::endl; } return ret;}
UTF-8是多字节字符串(multibyte string),而Unicode是宽字符字符串(wchar_t string)。
而C++11供给了wstring_convert这个类,这个类能够在wchar_t string和multibyte string之间往返转换;
而codecvt_utf8能够供给UTF-8的编码规矩。这个类在#include 《codecvt》中。有了wstring_convert供给宽字符字符串到多字节字符串的转化,而这个转换规矩由codecvt_uft8供给。如许子便可以实现UTF8和Unicode的相互转换。
从UTF8到Unicode挪用成员函数wstring_convert::from_bytes;
从Unicode到UTF8挪用成员函数wstring_convert::to_bytes;
Unicode 《=》 ANSI
std::string UnicodeToANSI(const std::wstring & wstr){ std::string ret; std::mbstate_t state = {}; const wchar_t *src = wstr.data(); size_t len = std::wcsrtombs(nullptr, &src, 0, &state); if (static_cast《size_t》(-1) != len) { std::unique_ptr《 char [] 》 buff(new char[len + 1]); len = std::wcsrtombs(buff.get(), &src, len, &state); if (static_cast《size_t》(-1) != len) { ret.assign(buff.get(), len); } } return ret;}std::wstring ANSIToUnicode(const std::string & str){ std::wstring ret; std::mbstate_t state = {}; const char *src = str.data(); size_t len = std::mbsrtowcs(nullptr, &src, 0, &state); if (static_cast《size_t》(-1) != len) { std::unique_ptr《 wchar_t [] 》 buff(new wchar_t[len + 1]); len = std::mbsrtowcs(buff.get(), &src, len, &state); if (static_cast《size_t》(-1) != len) { ret.assign(buff.get(), len); } } return ret;}
尺度库供给了wcsrtombs和mbsrtowcs这两个函数,固然C的尺度库也供给了这两个函数。
讲下wcsrtombs,这个函数把宽字符串转成多字节字符串。编码规矩受地区的LC_CTYPE影响。因而这个函数能够用于当地码的转化(和当地的编码息息相干)。
因而,有对于当地码的应用,在代码中要加高低列语句:
setlocale(LC_CTYPE, “”);
目标是让当地码失效,这条代码的感化就是让C++言语的Locale(地区)和当地的地区雷同。在Linux下能够运转locale下令看看:

能够看到,LC_CTYPE = en_US.UTF-8,这表现英文,英国,UTF-8编码,也就是说当地码就是这个。
固然,你也能够在setlocale中指定一些编码规矩,把wcsrtombs用于其余编码转化,然而,这里不推举,由于setlocale是全局的,设置了这个就会影响其余处所的编码。
wcsrtombs的四个参数分辨代表甚么意思呢?
std::size_t wcsrtombs( char* dst, const wchar_t** src, std::size_t len, std::mbstate_t* ps );
dst,转化后的成果存入dst指向的内存;
src,待转化的字符串的指针的指针;
len,dst指向内存的可用字节数;
ps,转换的状况,个别默许初始化就好了;
return type,转化后成果的长度,不包括。
留神:假如dst == nullptr,这个时间wcstombs的前往值表现会有这么多字节的成果发生,因而,咱们能够拿到这个前往值去新建一个数组来存储new char[len + 1]。以是,个别挪用两次wcstombs。
mbsrtowcs同理。
UTF-8 《=》 ANSI
以Unicode为中介装换就是。
std::string UTF8ToANSI(const std::string & str){ return UnicodeToANSI(UTF8ToUnicode(str));}std::string ANSIToUTF8(const std::string & str){ return UnicodeToUTF8(ANSIToUnicode(str));}
总结
C++11的尺度库仍是挺强盛的,固然这么强盛,然而良多特征还不懂得,因而仍是要多扩宽本人的视线,否则有好货色都不晓得用,那就棒棰了。
对了,在Linux下加上setlocale(LC_CTYPE, “”)后顺序在下令行中能够畸形表现,不加有可能不畸形表现,缘由是setlocale(LC_CTYPE, “”)也影响了cout,全局的嘛;而在CodeBlocks下不能畸形表现,不晓得为甚么,然而调试的进程中,视察到了畸形的成果;Visual Studio中没有做试验,不外应当没成绩。

更多内容阅读推荐:空调结冰怎么处理
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

无图版|手机版|计算机技术论坛 JSJBBS.CN @ 2008-2024 ( 鲁ICP备17021708号 )

技术支持 : 北京康盛新创科技有限责任公司

快速回复 返回顶部 返回列表