为什么mbstowcs返回“无效的多字节字符”

时间:2011-06-19 04:41:22

标签: c++ c utf-8 utf-16

"קמ"ד חיר!"是从gdb中变量的打印粘贴的输入字符串副本。调用mbstowcs返回-1,另一个输入为NULL。关于什么是错误/如何解决这个问题的任何想法?

"\327\247\327\236"\327\223 \327\227\327\231\327\250!\000\000\000"是八进制中带有非ascii字符的字符串

程序区域设置为C.

2 个答案:

答案 0 :(得分:3)

mbtowcs函数不处理UTF-8编码,没有可以设置的语言环境将UTF-8转换为wchar_t。因此,我将使用Windows示例,但大多数操作系统的一般想法是相同的。

在多字节字符集世界中,给定八进制值可能没有一个含义,并且对于任何给定字符,可能没有一个八进制值。特定八进制值的含义以及字符的表示方式(或者,如果可以表示),由locale确定。

当mbstowcs返回错误时,它基本上告诉你没有相当于传递给它的多字节字符的宽字符。这可能意味着没有UNICODE字符(不太可能但不是不可能)或者它可能意味着语言环境没有为给定的八进制值定义字符(或者在多字节字符的情况下为八进制值序列)。

如果您没有明确设置语言环境(通过调用setlocale),那么您将获得基于系统配置的语言环境。要检索当前的区域设置,您可以调用_get_current_locale。一旦你知道你的语言环境,就可以弄清楚特定八进制值代表什么字符(如果有的话),然后你可以弄清楚UNICODE等价物是什么(如果有的话)。

识别问题字符的一种方法是改变传递给mbstowcs的长度,直到找到导致错误的单个字符。蛮力方法可能是从长度= 1开始并增加它直到mbstowcs返回-1。

7月25日更新

从评论讨论中我们发现输入字符串(很可能)编码为UTF-8。虽然原始答案是正确的(到目前为止),但还远远不够。在Windows上,您无法创建将处理以UTF-8编码的字符的语言环境。

当面对UTF-8时,我们可以使用代码页CP_UTF8调用MultiByteToWideChar,而不是调用mbtowcs,但该代码只能在Windows上运行...

BYTE bytes [] = {0xD7,0x99,0xD7,0x95,0xD7,0x97,0xD7,0x90,0xD7,0x99,0x20,0xD7,0x95,0xD7,0x9B,0xD7,0x98,0xD7,0xA8, 0x00};

int result;

// get length of converted string in characters
result = MultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, (char *)bytes, 
    sizeof (bytes), NULL, 0);

wchar_t * name = new wchar_t [result];

// convert string
result = MultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, (char *)bytes, 
    sizeof (bytes), name, result);

答案 1 :(得分:1)

我敢打赌如果你像这样设置UTF-8会有效:

setlocale(LC_CTYPE, "UTF-8");