C++中如何通过Unicode值丂获取GB18030代码点8140?
如何将Unicode值转换为GB18030编码
你的核心问题是当前代码没有实现Unicode到GB18030的编码转换,反而在输出UTF-16的字节流,同时源文件编码问题导致直接写L"丂"时得到了错误的宽字符值。以下是修正方案:
问题分析
- 当前使用的
std::codecvt_utf16仅用于处理UTF-16与宽字符的转换,和GB18030编码无关。你看到的00 81 00 40是源文件编码不匹配导致的错误宽字符:如果你的源文件编码是GB18030,编译器会把L"丂"解析为GB18030的两个字节0x81和0x40,分别转成宽字符0x0081和0x0040,再转成UTF-16LE字节就得到了00 81 00 40;而L"\u4E02"是直接指定Unicode值,所以得到的是正确的宽字符0x4E02,转成UTF-16LE字节就是4e 02。 - 你需要的是将Unicode字符(
U+4E02)转换为GB18030编码的字节流,正确的GB18030编码丂应为81 40(两个字节)。
解决方案
方案1:使用标准库codecvt_byname(跨平台/Windows兼容)
通过指定GB18030编码的codecvt_byname转换器,实现宽字符(UTF-16)到GB18030的转换:
#include <iostream> #include <iomanip> #include <codecvt> #include <locale> void hex_print(const std::string& s); int main() { // 正确指定Unicode值U+4E02 std::wstring test2 = L"\u4E02"; // 创建GB18030编码转换器 std::wstring_convert<std::codecvt_byname<wchar_t, char, std::mbstate_t>> conv( new std::codecvt_byname<wchar_t, char, std::mbstate_t>("GB18030") ); // 转换为GB18030编码的字节流 std::string gb18030_str = conv.to_bytes(test2); hex_print(gb18030_str); return 0; } void hex_print(const std::string& s) { std::cout << std::hex << std::setfill('0'); for (unsigned char c : s) std::cout << std::setw(2) << static_cast<int>(c) << ' '; std::cout << std::dec << '\n'; }
方案2:使用ATL的CString(Windows专属)
因为你已经包含了<atlstr.h>,可以直接利用CString的编码转换功能:
#include <iostream> #include <atlstr.h> #include <iomanip> void hex_print(const std::string& s); int main() { std::wstring test2 = L"\u4E02"; // 将宽字符转换为GB18030编码的多字节字符串 CStringA gb18030_str(CStringW(test2), CP_GB18030); hex_print(static_cast<std::string>(gb18030_str)); return 0; } void hex_print(const std::string& s) { std::cout << std::hex << std::setfill('0'); for (unsigned char c : s) std::cout << std::setw(2) << static_cast<int>(c) << ' '; std::cout << std::dec << '\n'; }
输出结果
两个方案都会输出:
81 40
这就是丂对应的GB18030编码字节流。
内容的提问来源于stack exchange,提问作者Ferrus
相关产品推荐
相关产品推荐

