2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




Начать новую тему Ответить на тему На страницу 1, 2  След.
 
 Юникод и работа с ним
Сообщение28.08.2018, 12:01 
Заслуженный участник
Аватара пользователя


30/01/06
67802
aa_dav в сообщении #1334994 писал(а):
Одну из подлинных трагедий С++... можно увидеть как раз в чарах.
...
в) то есть целочисленного байта в языке так и не появилось

Добавлю к этой печальной повести, что потом наступили 90-е - 00-е, и 256 значений для символов стало не хватать. В C++ про запас ввели wchar_t, но потом оказалось, что он плохо подходит к разработанному позже Unicode. Языкам "поколения 90-х" в этом смысле больше повезло: они просто включали в себя "юникодовые символы" и "юникодовые строки", как бы они ни были имплементированы.

 Профиль  
                  
 
 Re: Перегрузка в С++ в зависимости от типа
Сообщение28.08.2018, 13:04 
Заслуженный участник


20/08/14
5502
Россия, Москва
Учитывая что Unicode символ легко может не влезть даже в uint64 - да-да, очень даже легко, несмотря на диапазон в чуть больше миллион кодов, есть же и непечатные модификаторы символов, которые логически относятся к самому символу и должны быть неотделимы от него при обработке - то всё ещё более грустно даже с новыми языками. Правда я не проверял сколько байтов может занимать Unicode символ в новых языках, если и более десятка байтов допустимо, то тут я не прав.

 Профиль  
                  
 
 Re: Перегрузка в С++ в зависимости от типа
Сообщение28.08.2018, 13:43 
Заслуженный участник
Аватара пользователя


30/01/06
67802
Dmitriy40 в сообщении #1335047 писал(а):
есть же и непечатные модификаторы символов, которые логически относятся к самому символу и должны быть неотделимы от него при обработке

Совсем всё грустно с модификаторами, которые указывают направление письма "слева направо" или "справа налево". В общем, обработка Unicode - наука, в которой можно быть отдельным профессионалом.

 Профиль  
                  
 
 Re: Перегрузка в С++ в зависимости от типа
Сообщение28.08.2018, 15:08 
Заслуженный участник
Аватара пользователя


16/07/14
2842
Москва
Dmitriy40 в сообщении #1335047 писал(а):
Правда я не проверял сколько байтов может занимать Unicode символ в новых языках, если и более десятка байтов допустимо, то тут я не прав.
В разговоре о юникоде лучше вообще не произносить слова "символ". Code point гарантированно в 32 бита влезает. Grapheme может иметь неограниченную длину, вроде ē̄̄̄̄̄̄̄̄̄̄̄̄̄̄̄̄̄̄̄.

 Профиль  
                  
 
 Re: Перегрузка в С++ в зависимости от типа
Сообщение28.08.2018, 16:29 
Заслуженный участник


20/08/14
5502
Россия, Москва
mihaild в сообщении #1335081 писал(а):
В разговоре о юникоде лучше вообще не произносить слова "символ".
Ещё букварь нас учит что текст на русском языке состоит из слов, а те из букв (знаков, символов, для нас это всё синонимы). Unicode претендует на описание текста в том числе на русском языке, т.е. состоящем из букв (aka символов). И боюсь если я начну в документации к русскоязычному текстовому редактору массово пользоваться термином графема вместо термина буква или символ - меня лишат премии или уволят.
И не надо что мол все русские буквы влезают в code point - не влезают, любая буква с банальным ударением уже требует два code point, отчего буквой (неделимым объектом) в смысле работы с текстом быть не перестаёт.
Во что превратится код быстрых алгоритмов поиска подстрок, заточенных под символы фиксированной длины, для unicode текста я заранее в ужасе, как бы они не стали медленнее последовательного просмотра, или вообще нерабочими. Благо что скорость поиска текста уже давно никого не волнует. А вот занимаемое место в памяти очень даже волнует, по крайней мере в сфере моих интересов (микроконтроллеры). И ещё больше волнует обработка unicode строк, если для константных строк ещё можно их препроцессингом конвертнуть в удобную кодировку (единственно поддерживаемую внешними устройствами типа символьных индикаторов!) на этапе компиляции, то для получаемых из внешних источников это невозможно и приходится городить небоскрёбы кода для преобразования кодировок. И даже для графических индикаторов проблема не уходит т.к. размер unicode шрифтов давно стал общим местом. Далеко не каждый МК имеет десятки мегабайт памяти, очень распространены и востребованы и МК с десятком килобайт. И если ему придёт по каналу связи unicode строка ... :facepalm:
PS. Простите, просто меня постоянно напрягают проблемами когда рабочий проект или перестаёт компилиться, или не работает (и без всяких UB как в этой теме) - по причине смены версии компилятора на более новую. А всего лишь разработчики наконец-то сменили тип строк с CP1251 на Unicode, ведь это же круто и мейнстрим, нативная поддержка всех мировых языков ... И если исправить программу ещё кое-как возможно (далеко не каждому, квалификация нужна сильно повыше "ардуинщиков"), то что делать с не имеющей понятия об unicode аппаратурой - вопрос больной.

 Профиль  
                  
 
 Re: Перегрузка в С++ в зависимости от типа
Сообщение28.08.2018, 16:36 
Заслуженный участник
Аватара пользователя


27/04/09
24082
Уфа
aa_dav
EtCetera
Спасибо, не знал и почему-то так решил.

-- Вт авг 28, 2018 18:44:24 --

Dmitriy40 в сообщении #1335089 писал(а):
Во что превратится код быстрых алгоритмов поиска подстрок, заточенных под символы фиксированной длины, для unicode текста я заранее в ужасе
Да не рассматривайте вы буквы как символы строки, рассматривайте как подстроки. Не всё так плохо. Кажется, такой алгоритм не должен сломаться ни если строка кодируется в какой-то из UTF16, ни в UTF-8 (UTF-32 и подавно, но по понятным причинам она почти не используется). Вообще часто выделять из строки отдельные графемы или кодпойнты не нужно.

 Профиль  
                  
 
 Re: Перегрузка в С++ в зависимости от типа
Сообщение28.08.2018, 20:26 
Заслуженный участник
Аватара пользователя


02/08/11
5380

(Оффтоп)

Dmitriy40 в сообщении #1335089 писал(а):
и приходится городить небоскрёбы кода для преобразования кодировок
Я неоднократно писал ручную конвертацию из UTF-8 в CP1251 и обратно и небоскрёбов как-то не заметил.

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

 Профиль  
                  
 
 Re: Перегрузка в С++ в зависимости от типа
Сообщение28.08.2018, 21:37 
Заслуженный участник


20/08/14
5502
Россия, Москва
warlock66613 в сообщении #1335132 писал(а):
Я неоднократно писал ручную конвертацию из UTF-8 в CP1251 и обратно и небоскрёбов как-то не заметил.
Возможно Вам повезло или Вы делали ограниченную поддержку. Например не учитывали возможность появления символов (типа Ё и Й) в NFD форме или со знаками ударений или с указанием начертания или неправильно (с лишними байтами) закодированных UTF8, да много чего может попасться. Я честное преобразование так и не собрался с духом писать, как окинул взором это море вариантов, так руки и опустились и ограничился использованием в устройствах одной CP1251 кодировки и преобразованием через кажется WideCharToMultiByte из WinAPI и пусть винда сама мучается. Или тупо проигнорировал все эти варианты и реализовал лишь простейший, с ним то проблем нет, Вы правы.
Возможно я излишне усложняю себе задачу.

 Профиль  
                  
 
 Re: Перегрузка в С++ в зависимости от типа
Сообщение28.08.2018, 22:12 
Заслуженный участник
Аватара пользователя


30/01/06
67802
warlock66613 в сообщении #1335132 писал(а):
и обычно это удаётся

Щас в подобный текстовый редактор превращается любое поле ввода в какой-нибудь GUI формочке. Как вы отличите
    "á" U+00E1
    "á" U+0061 U+0301
а точнее, опознаете, что это одно и то же, просто по-разному набранное? В любой базе данных *) может встретиться и то и другое из разных источников, и юзер будет долго тереть глаза, не найдя поиском одно по другому.
    "IJ" U+0132
    "IJ" U+0049 U+004A
Капитализация тоже доставляет. Как правильно?
    "ß" U+00DF -> "SS" U+0053 U+0053
    "ß" U+00DF -> "ẞ" U+1E9E
Сравнение и поиск, независимые от case, нужны частенько.
(И это всё только Европа, даже западная, только латиница.)

*) Пример: делаем симулятор электросхем, в котором юзер может обозначать элементы, как захочет. А он захочет непременно на своём родном языке.

 Профиль  
                  
 
 Re: Перегрузка в С++ в зависимости от типа
Сообщение28.08.2018, 22:50 
Заслуженный участник
Аватара пользователя


16/07/14
2842
Москва
Dmitriy40 в сообщении #1335089 писал(а):
Unicode претендует на описание текста в том числе на русском языке
Unicode претендует на представление текста.
Dmitriy40 в сообщении #1335089 писал(а):
если я начну в документации к русскоязычному текстовому редактору массово пользоваться термином графема вместо термина буква или символ - меня лишат премии или уволят
Тут нужно понять, на кого рассчитан редактор и документация. На практике в каком-нибудь WYSIWYG редакторе скорее всего нужно сразу ко всему что попало в редактор NFD применять.
Dmitriy40 в сообщении #1335089 писал(а):
Во что превратится код быстрых алгоритмов поиска подстрок, заточенных под символы фиксированной длины, для unicode текста я заранее в ужасе, как бы они не стали медленнее последовательного просмотра, или вообще нерабочими.
Тут надо принять волевое решение, считать ли вхождения без combining mark вхождениями. Если считать - то перед обработкой срубить всё странное. Если не считать - то проверять, что справа от найденного вхождения нет ничего, что должно было бы быть во вхождении.
Dmitriy40 в сообщении #1335089 писал(а):
букв (знаков, символов, для нас это всё синонимы)
Тем не менее, если кто-то говорит о unicode и хочет, чтобы его поняли - ему ИМХО лучше пользоваться стандартной терминологией.
arseniiv в сообщении #1335090 писал(а):
Кажется, такой алгоритм не должен сломаться ни если строка кодируется в какой-то из UTF16, ни в UTF-8 (UTF-32 и подавно, но по понятным причинам она почти не используется).
Только если нас устраивает, что в строке U+0061 U+0301 U+0062 находится a, находится b, причем визуально на соседних позициях, а вот ab уже не находится.
Munin в сообщении #1335159 писал(а):
Капитализация тоже доставляет
Она еще и за пределы ASCII выводит - в турецком U+0049 (I) в нижнем регистре - U+0131 (ı).

 Профиль  
                  
 
 Re: Перегрузка в С++ в зависимости от типа
Сообщение28.08.2018, 23:29 
Заслуженный участник
Аватара пользователя


30/01/06
67802
Я просто скромно пискну, что в некоторых языках само понятие капитализации не имеет смысла, зато с текстом бывают другие преобразования.

В простом и незамысловатом корейском языке слово hangeul "한글" U+D55C U+AE00 состоит из шести букв:
    h "ㅎ" U+314E,
    a "ㅏ" U+314F,
    n "ㄴ" U+3134,
    k "ㄱ" U+3131,
    eu "ㅡ" U+3161,
    r "ㄹ" U+3139
и оно должно демонстрировать это при поиске любой подстроки из них :-) Не говоря уже о вариантах "ᄂᅠ" U+1102, "ᅟᅠᆫ" U+11AB, "ᄀᅠ" U+1100, "ᅟᅠᆨ" U+11A8, "ᄅᅠ" U+1105, "ᅟᅠᆯ" U+11AF.

В простом и незамысловатом японском языке バカ, 馬鹿 и ばか означают одно и то же, и должны матчиться :-) А может, и не должны: это, честно говоря, надо уточнять у юзера.
И для пущего удовольствия, 抱き締める, 抱締める (!) и 抱きしめる означают одно и то же.

Да что там, в простом и незамысловатом английском языке naive и naïve - одно и то же слово...

 Профиль  
                  
 
 Re: Перегрузка в С++ в зависимости от типа
Сообщение29.08.2018, 00:23 
Заслуженный участник


20/08/14
5502
Россия, Москва
Добавлю всё же и сюда что я выше имел в виду под торможением и сломом быстрых алгоритмов поиска подстрок. Многие из них (типа Бойера-Мура) основаны на уменьшении количества сравнений с каждого символа входного текста (как для Кнута-Морриса-Пратта) до каждого n-го (в идеале n - длина искомой подстроки) до нахождения частичного совпадения (после нахождения которого остаток уже проверяется посимвольно). И тут критично что смещение следующего проверяемого символа вычисляется в терминах/единицах символов, а не байтов/слов, и преобразовать это смещение к количеству байтов во входном тексте для символов нефиксированной длины нереально без посимвольного просмотра текста (может и есть какие-то эвристики, не в курсе, но не думаю что кардинальные), от чего собственно и уходили, т.е. такой "быстрый" алгоритм будет медленнее посимвольного просмотра текста (распознающим автоматом). А без преобразования можно легко попасть в середину символа или не в тот символ и без принятия специальных мер алгоритм поиска сломается.
Т.е. такие алгоритмы перестают быть хорошими для любого алфавита с непостоянной длиной символов, не только unicode или тем паче utf8.

 Профиль  
                  
 
 Re: Юникод и работа с ним
Сообщение29.08.2018, 02:22 
Заслуженный участник
Аватара пользователя


16/07/14
2842
Москва
Dmitriy40 в сообщении #1335184 писал(а):
Т.е. такие алгоритмы перестают быть хорошими для любого алфавита с непостоянной длиной символов, не только unicode или тем паче utf8.
Если кодирование
1) однозначно - искомое совпадение подстрок обязательно будет побайтовым
2) обладает свойством "код любого символа не может быть собственным префиксом или суффиксом другого кода"
то мы можем игнорировать знания о символах, и работать со строками как с последовательностями байт.
Если есть первое свойство, но нет второго, то у нас могут быть лишние совпадения. Например, U+0061 найдется в строке U+0061 U+0307. Но для юникода это несложно пофильтровать потом (достаточно проверить один codepoint после вхождения).

 Профиль  
                  
 
 Re: Юникод и работа с ним
Сообщение29.08.2018, 20:15 
Заслуженный участник


20/08/14
5502
Россия, Москва
mihaild
Пример: ищем строку abcd, проверяем справа налево (Бойер-Мур), нам первым же шагом надо сравнить 4-й символ входного текста с d. Внимание вопрос: по какому байтовому смещению нужно взять code point в кодировке UTF32 чтобы попасть гарантированно на 4-й символ произвольного входного текста в Unicode (в UTF32 разумеется) с кучей ударений, умляутов, выбором направления письма, и прочими непечатными символами среди первых трёх символов текста? Ответ: неизвестно, надо идти по тексту по code point и делить поток кодов на символы и искать 4-й символ. У Вас есть другой ответ, более быстрый?!
Если 4-й символ не один из abcd, то дальше надо проверять уже 8-й символ - и снова та же проблема, получить его смещение в буфере если длина 5-го, 6-го, 7-го символов может быть очень разной (не всегда 4 байта).
И так далее.
Итого: вместо сравнений лишь каждого 4-го символа пришлось идти по тексту посимвольно и скорость "быстрого" метода поиска свелась к скорости "обычного" (Кнута-Морриса-Пратта). Вах.

PS. Предлагаю всем ЗУ снять тег офтопика в своих сообщениях, раз уж выделили в отдельную тему. Модераторы делать чужую работу не рвутся. ;-)

 Профиль  
                  
 
 Re: Юникод и работа с ним
Сообщение29.08.2018, 21:06 
Заслуженный участник
Аватара пользователя


16/07/14
2842
Москва
Dmitriy40 в сообщении #1335365 писал(а):
Внимание вопрос: по какому байтовому смещению нужно взять code point в кодировке UTF32 чтобы попасть гарантированно на 4-й символ произвольного входного текста в Unicode (в UTF32 разумеется) с кучей ударений, умляутов, выбором направления письма, и прочими непечатными символами среди первых трёх символов текста?
А зачем нам тут графема? Давайте искать 4й code point. Его адрес в UTF32 найти могу даже я.
Т.е. давайте искать подстроку в смысле code point, а не графем. В случае UTF8 - можно даже искать подстроку в смысле байт (хотя если шаблон и текст - корректные UTF8, то вхождения шаблона в текст как байтовой строки и как последовательности code point совпадают).

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 29 ]  На страницу 1, 2  След.

Модераторы: Karan, PAV, Toucan, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group