2014-01-14 1 views
4

Я знаю, что этот вопрос задавался довольно много раз здесь, и я прочитал некоторые из ответов. Но есть несколько предлагаемых решений, и я пытаюсь выяснить лучшие из них ,Преобразование текста UTF-8 в wchar_t

Я пишу приложение C99, которое в основном получает XML-текст, закодированный в UTF-8.

Часть из его работы состоит в том, чтобы скопировать и манипулировать эту строку (найти SUBSTR, кот его, бывшего ..)

Как я предпочел бы не использовать внешнюю не-стандартную библиотеку прямо сейчас, им пытается реализуйте его с помощью wchar_t.

В настоящее время im использует mbstowcs, чтобы преобразовать его в wchar_t для удобства манипуляции, а для некоторого ввода я попробовал на разных языках - он работал нормально.

Вещь, я прочитал некоторые люди, там были некоторые проблемы с UTF-8 и mbstowcs, поэтому я хотел бы услышать о том, разрешено ли это использование/приемлемо.

Другим вариантом, с которым я столкнулся, был использование iconv с параметром WCHAR_T. Дело в том, что я работаю на платформе (а не на ПК), которой он является очень ограниченным только для локали ANSI C. Как насчет этого?

Я также столкнулся с некоторой библиотекой C++, которая очень популярна. но им ограничен для реализации C99.

Кроме того, я бы скомпилировал этот код на другой платформе, размер size of wchar_t отличается (2 байта против 4 байтов на моей машине). Как я могу это преодолеть? используя контейнеры с фиксированным размером? но тогда, какие функции манипуляции я должен использовать вместо этого?

Счастливые услышать некоторые мысли. Благодарю.

+0

Вы * будете * сталкиваться с трудностями и иметь проблемы, я им гарантирую. UTF-8 является кодировкой, 'wchar_t' является деталью хранения, эти два не связаны друг с другом. 'wchar_t' просто упрощает обработку UTF-16, но как насчет суррогатных пар? Многобайтовые одиночные символы в UTF-8? – Dai

+0

Спасибо. не могли бы вы объяснить? –

+0

Что не так с mbstowcs? –

ответ

2

C не определяет, какие кодировки имеют типы char и wchar_t, а стандартная библиотека выполняет только некоторые функции, которые переводят между ними, не сказав, как это сделать. Если зависящая от реализации кодировка char не является UTF-8, то mbstowcs приведет к повреждению данных.

Как отмечалось в the rationale for the C99 standard:

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

...

C90 сознательно предпочел не изобретать более полную библиотеку с множеством и широкими знаками, вместо этого предпочитая ждать своего естественного развития, поскольку сообщество C приобрело больше опыта с широкими персонажами.

От источника here.

Итак, если у вас есть UTF-8 данные в ваш char s не существует стандартный API способ преобразования, что wchar_t с.

По-моему, wchar_t следует избегать, если это необходимо, - это может понадобиться, если вы используете API WIN32, например. Я не уверен, что это упростит манипуляции с строкой. wchar_t - это всегда UTF-16LE в Windows, поэтому вам все равно нужно иметь более одного wchar_t, чтобы представить единую кодовую точку Unicode.

Предлагаю вам изучить ICU project - по крайней мере, с точки зрения образования.

+0

Спасибо большое! Я заработал некоторую информацию о ICU, но я не нашел полезных примеров. Должен ли я использовать ICU только для преобразования строки, или у нее есть какие-либо функции для манипуляции строками? –

+0

Я предлагаю вам начать с [API ICU] (http://icu-project.org/apiref/icu4c/), чтобы узнать, соответствует ли он вашим потребностям. – McDowell

+0

Как я понял, чтобы хорошо работать со строковыми функциями манипуляции (как описано здесь [ссылка] (http://www.icu-project.org/apiref/icu4c/ustring_8h.html#details)) на UTF-8 строка в ICU, мне придется преобразовать мою строку в UTF-16. Вопрос в том, что если какая-то моя строка включает буквы, которые используют 3-4 байта в UTF-8, как они «переводится» на UTF-16, который использует 1-2 байта? –

1

Кроме того, я бы компиляции этого кода на другую платформу, которую SizeOf из wchar_t отличается (2 байта против 4 байта на моей машине). Как я могу это преодолеть? используя контейнеры с фиксированным размером?

Вы можете сделать это с условными определениями типов, как это:

#if defined(__STDC_UTF_16__) 
    typedef _Char16_t CHAR16; 
#elif defined(_WIN32) 
    typedef wchar_t CHAR16; 
#else 
    typedef uint16_t CHAR16; 
#endif 

#if defined(__STDC_UTF_32__) 
    typedef _Char32_t CHAR32; 
#elif defined(__STDC_ISO_10646__) 
    typedef wchar_t CHAR32; 
#else 
    typedef uint32_t CHAR32; 
#endif 

Это будет определять и определения типов CHAR16CHAR32 использовать новые C++ 11 типов символов, если таковой имеются, но в противном случае падения назад к использованию wchar_t, когда это возможно, и целые числа без знака фиксированной ширины в противном случае.

Смежные вопросы