我正在尝试使用C ++语言环境将CP936中的双字节字符序列(DBCS)转换为wchar_t
。这是代码:
#include <iostream>
#include <locale>
#include <codecvt>
// 国 in CP936
char const src[] = "\xB9\xFA";
int main()
{
std::locale loc(".936");
typedef std::codecvt<wchar_t, char, std::mbstate_t> codecvt_type;
codecvt_type const & cvt = std::use_facet<codecvt_type>(loc);
std::mbstate_t state;
std::memset(&state, 0, sizeof(state));
char const * src_mid = src;
wchar_t buf[10];
wchar_t * buf_mid = buf;
std::codecvt_base::result res = cvt.in(state,
src, src + 2, src_mid,
buf, buf + 10, buf_mid);
int eno = errno;
std::cout << "res: " << +res << "\n"
<< "errno: " << eno << "\n";
return 0;
}
现在,转换始终以错误结束,errno
设置为42,即EILSEQ
。我调试了代码,我想我可以看到出了什么问题,但我不明白为什么。
出现问题的是最终导致调用MultiByteToWideChar()
的代码有这样的条件:
if ( ploc->_Isleadbyte[ch >> 3] & (1 << (ch & 7)) )
尽管源字符串AFAIK包含正确的前导字节和尾随字节,但从未采用此分支。我在调试器中检查了_Isleadbyte
数组,它全是零。所以这个将输入长度设置为2
的分支从不被采用,而是采用长度设置为1
的分支,因此MultiByteToWideChar()
失败,因为前导字节必须伴随尾随字节。
我甚至检查C_936.NLS
中是否存在C:\Windows\System32\
,所以这不应该是问题。
所以,我想问题是:这个问题是否在我的最终,测试代码,Windows操作系统设置,缺少组件?或者是Visual Studio 2015代码中的这个问题吗?
更新
所以我偶然发现了这个问题:Shift-JIS decoding fails using wifstrem in Visual C++ 2013
OP自己的答案显示了一种解决方法:
const int oldMbcp = _getmbcp();
_setmbcp(932);
const std::locale locale("Japanese_Japan.932");
_setmbcp(oldMbcp);
同样的解决方法似乎适用于我尝试使用的CP936。
更新2
我向微软提交了bug report。