почему mbstowcs возвращает «недопустимый многобайтовый символ» - PullRequest
1 голос
/ 19 июня 2011

"קמ"ד חיר!" - копия входной строки, вставленная из отпечатка переменной в GDB. Вызов mbstowcs возвращает -1 с другим вводом как NULL. Любые идеи о том, что не так / как это исправить?

"\327\247\327\236"\327\223 \327\227\327\231\327\250!\000\000\000" - строка с восьмеричными не ascii символами

Язык программы - C.

Ответы [ 2 ]

3 голосов
/ 19 июня 2011

Функция mbtowcs не обрабатывает кодировку UTF-8, нет локали, которую можно установить, чтобы она переводила UTF-8 в wchar_t.Поэтому я буду использовать примеры Windows, но общая идея одинакова на большинстве ОС.

В мире многобайтовых наборов символов не может быть одного значения для данного восьмеричного значения, и не может быть одного восьмеричного значения для любого заданного символа.Что означает конкретное восьмеричное значение и как символ представлен (или даже , если он может быть представлен), определяется locale .

Когда mbstowcs возвращает ошибку, он в основном говорит вам, что не существует широкого символа, эквивалентного переданному ему многобайтовому символу.Это может означать, что нет символа UNICODE (маловероятно, но не невозможно), или это может означать, что языковой стандарт не определяет символ для данного восьмеричного значения (или последовательность восьмеричных значений в случае многобайтовых символов).

Если вы явно не задаете свой языковой стандарт (вызывая setlocale ), вы получаете языковой стандарт на основе конфигурации вашей системы.Чтобы получить ваш текущий язык вы можете позвонить _get_current_locale .После того, как вы узнаете свою локаль, вы можете выяснить, какой символ (если есть) представляет конкретное восьмеричное значение, а затем вы можете выяснить, каким будет эквивалент UNICODE (если есть).

Один из способов выявления проблемысимвол должен изменять длину, передаваемую в mbstowcs, пока вы не найдете один символ, который вызывает ошибку.Подход грубой силы может состоять в том, чтобы начать с длины = 1 и увеличивать ее до тех пор, пока mbstowcs не вернет -1.

Обновление 25 июля

Из обсуждения комментариев мы обнаружили, чтовходная строка (скорее всего) кодируется как UTF-8.Хотя первоначальный ответ является правильным (насколько это возможно), он не заходит достаточно далеко.В Windows вы не можете создать локаль, которая будет обрабатывать символы, закодированные в UTF-8.

Столкнувшись с UTF-8, вместо вызова mbtowcs мы можем вызвать MultiByteToWideChar , используя кодовую страницу CP_UTF8, но этот код будет работать только в 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 голос
/ 05 августа 2012

Бьюсь об заклад, это будет работать, если вы установите UTF-8 следующим образом:

setlocale(LC_CTYPE, "UTF-8");
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...