c++ - MSVC 上的双字节编码 (std::codecvt):无法识别前导字节

标签 c++ windows visual-c++ unicode character-encoding

我想使用 std::codecvt<wchar_t, char, std::mbstate_t>::in() 将双字节代码页中编码的字符串转换为 UTF-16 字符串关于 Microsoft 标准库实现 (MSVC11)。例如,考虑以下程序:

#include <iostream>
#include <locale>

int main()
{
    // KATAKANA LETTER A (U+30A2) in Shift-JIS (Codepage 932)
    // http://msdn.microsoft.com/en-us/goglobal/cc305152
    char const cs[] = "\x83\x41";

    std::locale loc = std::locale("Japanese");

    // Output: "Japanese_Japan.932" (as expected)
    std::cout << loc.name() << '\n';

    typedef std::codecvt<wchar_t, char, std::mbstate_t> cvt_t;
    cvt_t const& codecvt = std::use_facet<cvt_t>(loc);
    wchar_t out = 0;
    std::mbstate_t mbst = std::mbstate_t();
    char const* mid;
    wchar_t* outmid;

    // Output: "2" (error) (expected: "0" (ok))
    std::cout << codecvt.in(
        mbst, cs,   cs + 2,   mid,
              &out, &out + 1, outmid) << '\n';

    // Output: "0" (expected: "30a2")
    std::cout << std::hex << out << '\n';
}

调试时发现in()最终调用内部 _Mbrtowc()函数(crt\src\xmbtowc.c),传递 std::locale 的内部(C?)部分,初始化为 {_Page=932 _Mbcurmax=2 _Isclocale=0 ...} ,其中...代表(这似乎是问题所在)_Isleadbyte成员,初始化为 32 个零的数组(类型为 unsigned char)。因此,当函数处理'\x32'时前导字节,它检查此数组并自然地得出(错误)结论:这不是前导字节。所以它很高兴地调用 MultiByteToWideChar() Win-API 函数当然无法转换半字符。所以,_Mbrtowc()返回错误代码 -1,这或多或少会取消调用堆栈上的所有内容,最终返回 2 ( std::codecvt_base::result::error )。

这是 MS 标准库中的错误吗(看起来是这样)? (如何)我可以以可移植的方式解决这个问题(即使用最少的 #ifdef s)?

最佳答案

我在内部向 Microsoft 报告了此事。现在已将其作为新错误进行了修复(DevDiv#737880)。但我建议填写连接项:http://connect.microsoft.com/VisualStudio

关于c++ - MSVC 上的双字节编码 (std::codecvt):无法识别前导字节,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17122277/

相关文章:

python - 如何使用 Python 与窗口的 GUI 交互?

c# - 如何调试DLL里面的代码

c++ - VC解决方案跨多个项目访问同一个对象

c++ - 无法访问集合中的集合 | C++

c++ - 如何找到对应于键 vector 的所有元素?

c - 通过 Hook 调用在 Windows 进程中加速或静音音频播放

windows - 使用图标作为文件类型,但不使用程序打开

c++ - 试图理解数组名称的含义

c++ - 如何打印其中包含整数的字符串 C++

c++ - 解析文件时输出错误?