////
【CPP开发者入门】:在与东方语言(中文、日文、韩文)打交道时,我们经常会遇到各种编码问题,并被此类问题所困惑。 当我在网上查找资料时,我仍然一头雾水。 最后常常错误地解决问题,至今仍一头雾水。
本文介绍了如何在最常见的编码方式(UTF-8、ANSI)之间进行转换,并结合代码示例,清晰易懂,读者也可以直接使用示例。 本文推荐给经常处理文本字符串的程序员,以便他们掌握一些字符转换的基本方法。
以下为正文
在C++项目中,字符编码是一个很大的陷阱。 不同平台之间的编码往往是不同的。 如果用一组字符读取格式读取不同的编码格式,就会出现乱码。 因此,一般会转换为UTF-8,一种全平台且支持良好的编码格式。
,关于UTF-8的概念我就不过多解释了。 这里先说一下ANSI。 我第一次看到这个术语时,我以为它是 ASCII。 受到严厉批评。
ANSI 是一种字符代码。 为了使计算机能够支持更多的语言,通常用0x00~0x7F范围内的1个字节来表示一个英文字符。 超出这个范围,使用0x80~进行编码,即扩展ASCII编码。
不同的国家和地区制定了不同的标准,产生了各自的编码标准,如GBK、Big5、Big5等。 这些使用多个字节表示一个字符的各种汉字扩展编码方法称为 ANSI 编码。 在简体中文操作系统中,ANSI编码代表GBK编码; 在繁体中文操作系统中,ANSI编码代表Big5; 在日文操作系统中,ANSI编码代表编码。
以上内容摘自百度百科。 可见ANSI和ASCII还是有联系的。 ANSI 也称为本地代码。
我们需要能够在UTF-8和ANSI这三种编码格式之间自由转换。 如下所示:
在C++中,如何做到这一点? 当然,我们使用标准库。 C++11仍然可以满足国际标准并提供这些接口。 如图中虚线所示,标准库没有提供UTF-8到ANSI的相互转换接口,但是我们可以自己封装转接接口,使用这条路径(UTF-8 ANSI)来实现。
因此,我们来谈谈UTF8和ANSI。
UTF8
我们先看代码:
std::string UnicodeToUTF8(const std::wstring & wstr)
{
std::string ret;
try {
std::wstring_convert< std::codecvt_utf8
> 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
> wcv; ret = wcv.from_bytes(str);
} catch (const std::exception & e) {
std::cerr << e.what() << std::endl;
}
return ret;
}
UTF-8 不是多字节字符串 ( ),而是宽字符串 ( )。
C++11提供了这个类,可以在and之间来回转换;
可以提供UTF-8编码规则。 该类位于 # 中。 随着宽字符串到多字节字符串的转换,转换规则由 提供。 这样UTF8和UTF8就可以互相转换了。
美国国家标准协会
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
(-1) != len) { std::unique_ptr< char [] > buff(new char[len + 1]);
len = std::wcsrtombs(buff.get(), &src, len, &state);
if (static_cast
(-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
(-1) != len) { std::unique_ptr< wchar_t [] > buff(new wchar_t[len + 1]);
len = std::mbsrtowcs(buff.get(), &src, len, &state);
if (static_cast
(-1) != len) { ret.assign(buff.get(), len);
}
}
return ret;
}
标准库提供了这两个函数,当然C标准库也提供了这两个函数。
接下来,该函数将宽字符串转换为多字节字符串。 编码规则受地区影响。 因此,该函数可以用于本地编码转换(与本地编码密切相关)。
因此,关于本地代码的使用,需要在代码中添加如下语句:
(,“”);
目的是使本地代码有效。 这段代码的作用是让C++语言(区域)和本地区域一致。 Linux下可以运行命令查看:
可以看到,=en_US.UTF-8,表示英语,英国,UTF-8编码,表示本地编码是这个。
当然,你也可以在其中指定一些编码规则,并将其转换为其他编码。 但不建议这样做,因为它是全局的,设置它会影响其他地方的编码。
四个参数的含义是什么?
std:: ( char* dst, const ** src, std:: len, std::* ps );
注意:如果dst ==,此时的返回值表示会生成这么多字节。 因此,我们可以得到这个返回值来创建一个新的数组来存储new char[len + 1]。 因此,通常会调用两次。
同样的原因。
UTF-8 ANSI
我觉得中介只是在假装。
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下添加(,“”)后,程序就可以在命令行中正常显示了。 如果不添加的话,可能无法正常显示。 原因是(,"")也会影响cout,cout是全局的; 但在Linux下无法显示。 显示正常,不知道为什么,但是在调试过程中,观察到正常结果; 我没有做过任何实验,但应该没问题。
关于C++字符编码,欢迎在评论中与我讨论。 如果您觉得文章不错,请点赞阅读,支持我继续分享好文章。 谢谢!