LINUX.ORG.RU

Unicode и C++ без wchar


0

1

В приложении требуется поддержка юникода, текст приходит из сети в utf-8. wchar_t и std::wstring в используемой платформе (анроид) нет.
Как организовать в таком случае работу со строчками в юникоде?
Пока есть мысль использовать маленькую библиотеку utf8-cpp для преобразования строчек в набор 32-битных кодов unicode и сделать свой std::basic_string для типа unsigned int.

★★★★★

Для хранения и обработки utf-8 достаточно типа char.

Проблема может появиться при выводе текста.

sched
()
Ответ на: комментарий от namezys

Таки возможно появится. Я не знаю как на андроиде, но в win, текст полученный в utf-8 по сети превращается в кракозябры.

sched
()
Ответ на: комментарий от sched

Это проблемы винды, ее консоли и твоих кривых рук. Кроме того ты не прав в том, что char достаточно для (удобной) обработки utf8-текста. Возьми к примеру строку и распечатай все гласные буквы, встреченные в ней.

staseg ★★★★★
()

Ответ наверное простой: заюзать short для хранения символов. Или uint16_t.

kiverattes ★☆
()
Ответ на: комментарий от staseg

>Это проблемы винды, ее консоли и твоих кривых рук.

Толсто. Я привёл пример, что на отдельных платформах могут возникнуть проблемы.

Возьми к примеру строку и распечатай все гласные буквы, встреченные в ней.

И как ты эту взятую с неба задачу решишь лучше используя int или что-то ещё?

sched
()
Ответ на: комментарий от staseg

>Возьми к примеру строку и распечатай все гласные буквы, встреченные в ней.

wchar и т.п. тоже не может решить эту проблему. Ведь 1 отображаемый символ UTF8 может состоять хоть из 10 простых символов UTF8. А каждый простой символ UTF8 может состоять из нескольких байт. Да ещё вопросы нормализации имеются, без которой невозможно легко вытащить только «чистые» символы.

anonymous
()

Перевод между UTF8 и UTF32 делается элементарно, тем более есть в интернете реализации этих простых функций.

Как вариант: 1) Разделить поток UTF8 на отдельные символы UTF32 в виде int32. 2) Провести нормализацию-декомпозицию. 3) Получить двухмерный массив, в котором по одному измерению будут отображаемые символы, по другому измерению переменной длины внутри отображаемого символа массив символов, в котором нулевой элемент является основным, а последующие элементы его модификаторами.

anonymous
()
Ответ на: комментарий от sched

Запортабился:), на андроид проблем с выводом не будет.

В общем случае для хранения достаточно char, возможно понадобтся сторонние библиотеки.

sched
()

Для хранения обычный чар покатит. Для обработки советую glib.

bk_ ★★
()
Ответ на: комментарий от sched

>Толсто. Я привёл пример, что на отдельных платформах могут возникнуть проблемы.

Это плохой пример. Ты получил валидный utf8 и превратил ее в «кракозябры». Еще раз внимательно посмотри на свои руки.

И как ты эту взятую с неба задачу решишь лучше используя int или что-то ещё?

ТС для этого и ищет готовое решение. Посимвольная обработка текста (сравнить буквы, узнать длину строки, может что-то еще) несколько геморройна стандартными средствами С++.

используя int или что-то ещё

Предварительно разбив тект на буквы («инты или что-то еще») ты сильно поможешь себе в дальнейшей обработке этих самых букв. Не забывай, что размер utf8-символа не фиксирован, и поэтому постоянно корячиться с char*-строкой неудобно.

staseg ★★★★★
()
Ответ на: комментарий от sched

не стоит такого делать. обрабатвать utf-8 достаточно сложно, ибо не знаешь сколько байт описывают один глиф

namezys ★★★★
()
Ответ на: комментарий от namezys

Рисовать через OpenGL, иногда редактировать, отправлять обратно.

Собственно, некоторое решение уже получилось практически само собой: написал функции-обертки для преобразования utf8 в utf32 и обратно, все строки заменил на std::basic_string<unsigned int> и работает.

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

note173 ★★★★★
() автор топика
Ответ на: комментарий от note173

Только не надо забывать, что, например, слово «сло́н» может состоять из следующих символов UTF8.
с d1 81
л d0 bb
о́ d0 be cc 81 (для одного отображаемого символа используется 2 символа UTF8)
н d0 bd

anonymous
()

Чуваки-бурлаки, а чё такое «два символа UTF-8»? Я думал, UTF-8 - это просто способ кодирования чисел от 0 до мегастопицот. Эти числа = коды в таблице UNICODE. Вы хотите сказать, что некоторые символы представляются двумя UNICODE-кодами (числами)? Нет -> «а чё тогда вы имеете ввиду», Да -> «никуя себе».

kiverattes ★☆
()
Ответ на: комментарий от anonymous

Нифига себе вы ссылки даёте, хотя-бы якорь привязали к конкретному месту. Чё-то как-то сложно. Чё, мало того пространства чисел для кодирования всех символов? Всякие акуты и точки над символами отдельно кодируются?

kiverattes ★☆
()
Ответ на: комментарий от kiverattes

Действительно сложно и надо прочитать весь текст, чтобы понять.

Всякие акуты и точки над символами отдельно кодируются?

Могут отдельно кодироваться, могут быть и отдельным символом. Для этого и существует разные формы нормализации, чтобы можно было сравнивать строки. Там по ссылке всё это описано.

anonymous
()

> wchar_t и std::wstring в используемой платформе (анроид) нет.

был какой-то порт NDK с поддержкой wchar

lazyklimm ★★★★★
()
Ответ на: комментарий от kiverattes

> Если я перестану, меня уволят за злостное непонимание работы std::string.

Я бы вас уже уволил за злостное непонимание того, что глиф и байт (или даже несколько байт) - не одно и тоже

namezys ★★★★
()
Ответ на: комментарий от namezys

А я у таких булочников, которые за такое увольняют, не работаю.

kiverattes ★☆
()
Ответ на: комментарий от namezys

Кстати, это я понимаю, байт и несколько байт - это единицы измерения кол-ва информации, а глиф - это не единица измерения кол-ва информации. Но я всё равно не работаю у таких булочников, которые приписывают мне фигню (-;

kiverattes ★☆
()
Ответ на: комментарий от kiverattes

глиф - единица отображения информации глиф кодируется последовательностью символов

namezys ★★★★
()
Ответ на: комментарий от lazyklimm

Есть такой, но официальный NDK уже ушел на 2 версии вперед, поэтому использую его.

note173 ★★★★★
() автор топика

Как всегда, человек задал вопрос, а злобные задроты начали поливать друг друга говном и придумывать похлеще, кто за что друг друга уволит.

Danmer ★★
()

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

Но сейчас, мне кажется, решение не будет столь уж простым, и те недостатки, которые всплывают при использования qt, меркнут на фоне плюсов. Так что QString. Правда не знаю, каков статус его портирования на андроид.

mi_estas
()
Ответ на: комментарий от namezys

вообще давно пора перестать мыслить о строке, как о наборе символов

чёт смело как-то, все классические учебники уверены в том, что строка - это набор символов, причём в широком смысле слова

может, уважаемый хотел сказать что-то другое?

shty ★★★★★
()
Ответ на: комментарий от anonymous

Я очень стараюсь не использовать сторонние библиотеки. Во-первых, размер бинарника важен (а код еще и компилируется под две версии arm). Во-вторых, в сдк андроида неполная реализация стандартной библиотеки с++.

note173 ★★★★★
() автор топика
Ответ на: комментарий от shty

Смотря что называть словом символ. Визуальную единицу, занимающее 1 знакоместо? Составную часть символа, которая и сама по себе является символом, но не используется самостоятельно, а только в составе других символов, включая даже пробел?
Для первого случая текст в юникоде можно представить двумерным массивом символов. Для второго случая текст может быть последовательностью кодов UTF32 в виде int32.

anonymous
()
Ответ на: комментарий от note173

Вот этот файлик содержит практически всю нужную информацию для работы с юникодом, включая вопросы нормализации http://www.unicode.org/Public/UNIDATA/UnicodeData.txt Работу с юникодом можно самому всю запрограммировать специально для своего случая, это не сложно, но если в этом разобраться.

anonymous
()

icu4c во все поля.

И вообще, c++, boost, icu4c - всё что надо сплюсплюснику.

anonymous
()
Ответ на: комментарий от anonymous

Смотря что называть словом символ. Визуальную единицу, занимающее 1 знакоместо? Составную часть символа, которая и сама по себе является символом, но не используется самостоятельно, а только в составе других символов, включая даже пробел?

вот только не надо смешивать человеко-понятное представление с абстрактным понятием (строка), оба два описанных Вами случая являются примерами строк

Для первого случая текст в юникоде можно представить двумерным массивом символов.

Вы опять закладываетесь на «символы», хотя это понятие не определили, двухмерный массив здесь - мимо

shty ★★★★★
()
Ответ на: комментарий от shty

Почему мимо? По одной координает отображаемый символ, по второй координате последовательноть символов юникода, из которой состоит это отображаемый символ.
Самая настоящая двумерная структура:

Строка «Почему́ ми́мо?»
d09f
d0be
d187
d0b5
d0bc
d183 cc81
20
d0bc
d0b8 cc81
d0bc
d0be
3f

anonymous
()

Я здесь один, кто поинтересуется, зачем юникод для не китайско-японских пользователей?

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от shty

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

anonymous
()
Ответ на: комментарий от Eddy_Em

как зачем? напишите что-нибудь на русском и испанском одновременно. Кодировки ведь придётся переключать посреди текста.

anonymous
()
Ответ на: комментарий от anonymous

Лично мне была нужна для решения конкретной задачи

с этого надо начинать

А двухмерное представление юникодного текста самое то было.

ты гонишь, это такая же строка, только символ в ней занимает два байта (например, не знаю сколько так у тебя байт было)

shty ★★★★★
()
Ответ на: комментарий от Eddy_Em

Я здесь один, кто поинтересуется, зачем юникод для не китайско-японских пользователей?

man Л. Толстой

shty ★★★★★
()
Ответ на: комментарий от shty

>чёт смело как-то, все классические учебники уверены в том, что строка - это набор символов, причём в широком смысле слова

Точки над 'ё' - это символ? А над 'Ü'?

legolegs ★★★★★
()
Ответ на: комментарий от legolegs

Точки над 'ё' - это символ? А над 'Ü'?

это называется умляут, какой язык?

shty ★★★★★
()
Ответ на: комментарий от shty

1 отображаемый символ может занимать в UTF-8 от 1 байта до неограниченного числа байт, от одного символа юникода до неограниченного числа символов юникода.

Например, задача: найти десятый символ. В случае одномерной строки символов юникода надо будет перебирать все символы подряд от начала до конца, искать начало и конец каждого отображаемого символа. В случае двумерной структуры — это простое обращение по индексу.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.