【问题标题】:Doublebyte encodings on MSVC (std::codecvt): Lead bytes not recognizedMSVC (std::codecvt) 上的双字节编码:无法识别前导字节
【发布时间】:2013-06-15 09:47:44
【问题描述】:

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

#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?)部分,初始化为@987654327 @,其中 ... 代表(这似乎是问题所在)_Isleadbyte 成员,初始化为 32 个零的数组(类型为无符号字符)。因此,当函数处理'\x32' 前导字节时,它会检查此数组并自然得出(错误的)结论,即这不是前导字节。所以它愉快地调用了MultiByteToWideChar() Win-API 函数,当然,它不能转换半角字符。因此,_Mbrtowc() 返回错误代码 -1,这或多或少取消了调用堆栈上的所有内容,最终返回 2 (std::codecvt_base::result::error)。

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

【问题讨论】:

  • 我复制。很难调试的代码,报告这个 connect.microsoft.com

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


【解决方案1】:

我在内部向 Microsoft 报告了这件事。现在已将其填充为一个新错误 (DevDiv#737880)。但我建议填写连接项:http://connect.microsoft.com/VisualStudio

【讨论】:

  • 谢谢!实际上,我并没有直接受到这个错误的影响,我在尝试为相关(第 3 方库)错误创建一个最小示例时发现了它。但我想我会花时间提交一个连接错误。
  • 不幸的是,我似乎无法提交错误:我陷入了一个循环,反复要求我完成所需的个人资料信息:connect.microsoft.com “完成您所需的个人资料信息”--(下一步)--> social.microsoft.com “编辑我的个人资料”--(保存)--> profile.microsoft.com “注册”--(下一步)--> (返回开始) .当然,我已经填写了所有必填 (*) 字段。
【解决方案2】:

我将您的代码复制粘贴到 VC2010 / Windows 7 64 位中。

它按您的预期工作。这是输出:

Japanese_Japan.932
0
30a2

这可能是 VC2012 引入的错误...

【讨论】:

    猜你喜欢
    • 2018-06-21
    • 2021-05-15
    • 2015-06-26
    • 1970-01-01
    • 2020-12-13
    • 2016-09-23
    • 1970-01-01
    • 2021-12-17
    • 1970-01-01
    相关资源
    最近更新 更多