2014-09-29 13 views
6

Я пишу некоторые функции преобразования строк, похожие на atoi() или strtoll(). Я хотел включить версию моей функции, которая принимала бы char16_t * или char32_t *, а не только char * или wchar_t *.C11 Поддержка Unicode

Моя функция работает нормально, но, как я ее писал, я понял, что не понимаю, что такое char16_t или char32_t. Я знаю, что стандарт требует только того, чтобы они были целыми типами не менее 16 или 32 бит соответственно, но импликация заключается в том, что они являются UTF-16 или UTF-32.

Я также знаю, что стандарт определяет несколько функций, но они не включали никаких функций * get или * put (как они делали, когда они добавили в wchar.h в C99).

Итак, мне интересно: что они ожидают от меня char16_t и char32_t?

+1

Преобразование в UTF-8, что еще? – Deduplicator

+0

@Deduplicator: Если это то, что они ожидали от вас, вам следует подумать, что они предоставили вам функции для этого ... –

+0

Планируете ли вы поддерживать не только '0..9' (U + 0030 .. U + 0039) (и, возможно, 'A..Z/a..z', до обычного обычного уровня, base-36), но все остальные символы, помеченные как« Numeric »в полной таблице Unicode? «Coz» включает в себя типографические формы (супер- и индексы, обведенные номера до 20 (!)) И специфические для сценариев формы (арабские цифры, ивритские номера), а также римские цифры, древнегреческий и «подсчетные стержни» и многое другое. – usr2564301

ответ

9

Это хороший вопрос без очевидного ответа.

Типы и функции, добавленные в C11, в значительной степени бесполезны. Они поддерживают только конверсии между новым типом (char16_t или char32_t) и специфичные для языка, многобайтовые кодировки с реализацией, сопоставления, которые не будут полными, если язык не основан на UTF-8. Полезные преобразования (в/из wchar_t и в/из UTF-8) не поддерживаются. Разумеется, вы можете сворачивать свои собственные для конверсий в/из UTF-8, поскольку эти преобразования на 100% заданы соответствующими стандартами RFC/UCS/Unicode, но будьте осторожны: большинство людей внедряют их неправильно и имеют опасные ошибки.

Обратите внимание, что новый компилятор уровень имеет для UTF-8, UTF-16 и UTF-32 литералы (u8, u и U, соответственно) являются потенциально полезными; вы можете обрабатывать полученные строки своими собственными функциями значимыми способами, которые вообще не зависят от языка. Но библиотека уровня поддержка Unicode в C11, на мой взгляд, в основном бесполезна.

+0

Знаете ли вы, насколько он ограничивает переносимость, предполагая, что многобайтовое кодирование UTF-8? (Я имею в виду, это что-то вроде «стандарт позволяет дополнение« не-2 », которое часто можно игнорировать на практике, или это действительно то, о чем я должен беспокоиться?) – mafso

+0

@mafso: Я не думаю, что * внутреннее * представление строк как UTF8 является потенциальной проблемой переносимости. Но как вы собираетесь отображать свой текст, если нет портативного (почти наверняка «за определение») способа показать результат? – usr2564301

+1

@ Jongware: Я знаю, что это не портативный (теоретически). Но это «специфичное для локали многобайтное кодирование» и «кодировка с широким кодированием по локали» стандартизовалось на C89, время, когда кодировки Unicode не были такими широко распространенными, как сегодня (IIRC они даже не были стандартизованный к тому времени). Мой вопрос: если в наши дни безопасно принимать кодировки Unicode _in practice_. – mafso

3

Тестирование, если чартер UTF-16 или UTF-32 в диапазоне ASCII является одним из «обычных» 10 цифр, +, - или «нормальное» белое пространство легко сделать, а также преобразовать '0'-'9' в цифра. Учитывая это, atoi_utf16/32() происходит как atoi(). Просто проверьте один символ за раз.

Тестирование, если некоторые другие UTF-16/UTF-32 - это цифра или пробел - это сложнее. Коду понадобится расширенный isspace(), isdigit(), который может быть переключен на локальные (setlocale()), если требуется местная локаль. (Примечание: вероятно, необходимо восстановить локаль, когда функция выполняется

Преобразование символа, который проходит isdigit(), но это не один из обычных 10 до его стоимости является проблематичным В любом случае, что появляется не даже запрещено...

шаги преобразования:

  1. Набор локаль к соответствующему одному для UTF-16/UTF-32

  2. использования isspace() ф. или обнаружение белого пространства.

  3. Convert аналогичный способ для your_atof().

  4. Восстановить локальные.

+0

И не забывайте, что UTF-16 и UTF-32 имеют варианты с большим и низким порядком, и вам все равно. – JohnH

+0

@JohnH: Как это может быть актуально для UTF-32? – mafso

+1

@mafso Варианты с большими/маленькими эндиантами применимы как к UTF-16, так и к UTF-32. На уровне _byte_ у 2 или 4 байтов есть порядок, который нечетко неверно соответствует порядку байта программного обеспечения. Это можно исправить с помощью различных функций переупорядочения байтов. С кодовой точкой Unicode> = 0x10000, а кодирование - UTF-16, порядок в двух суррогатах UTF-16 иногда встречается в большом или минимальном порядке. Только один из них является правильным (забыть, что).Когда используется некорректный, он должен указываться как ошибка кодирования, хотя некоторые системы являются мягкими (без подачи жалобы). – chux

0

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

Самый простой способ сделать это - написать функцию strtoull, используя тип char32_t (назовите это что-то вроде strtoull_c32). Это упрощает разбор юникода, потому что каждый символ в UTF-32 занимает четыре байта. Затем выполните strtoull_c16 и strtoull_c8, внутренне преобразуя кодировки UTF-8 и UTF-16 в UTF-32 и передавая их strtoull_c32.

Я честно не смотрел объекты Unicode в стандартной библиотеке C11, но если они не предоставляют подходящий способ для преобразования этих типов в UTF-32, то вы можете использовать стороннюю библиотеку, чтобы сделать преобразование для вас ,

Существует ICU, который был запущен IBM, а затем принят Консорциумом Unicode. Это очень многофункциональная и стабильная библиотека, которая существует уже давно.

Недавно я начал использовать библиотеку UTF (UTFX) для C89, которую вы могли бы использовать для этого. Это довольно простой и легкий, проверенный и документированный блок. Вы можете дать это или использовать его, чтобы узнать больше о том, как работают конверсии UTF.

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