2014 dxdy logo

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

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




На страницу 1, 2  След.
 
 Юникод и работа с ним
Сообщение28.08.2018, 12:01 
Аватара пользователя
aa_dav в сообщении #1334994 писал(а):
Одну из подлинных трагедий С++... можно увидеть как раз в чарах.
...
в) то есть целочисленного байта в языке так и не появилось

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

 
 
 
 Re: Перегрузка в С++ в зависимости от типа
Сообщение28.08.2018, 13:04 
Учитывая что Unicode символ легко может не влезть даже в uint64 - да-да, очень даже легко, несмотря на диапазон в чуть больше миллион кодов, есть же и непечатные модификаторы символов, которые логически относятся к самому символу и должны быть неотделимы от него при обработке - то всё ещё более грустно даже с новыми языками. Правда я не проверял сколько байтов может занимать Unicode символ в новых языках, если и более десятка байтов допустимо, то тут я не прав.

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

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

 
 
 
 Re: Перегрузка в С++ в зависимости от типа
Сообщение28.08.2018, 15:08 
Аватара пользователя
Dmitriy40 в сообщении #1335047 писал(а):
Правда я не проверял сколько байтов может занимать Unicode символ в новых языках, если и более десятка байтов допустимо, то тут я не прав.
В разговоре о юникоде лучше вообще не произносить слова "символ". Code point гарантированно в 32 бита влезает. Grapheme может иметь неограниченную длину, вроде ē̄̄̄̄̄̄̄̄̄̄̄̄̄̄̄̄̄̄̄.

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

 
 
 
 Re: Перегрузка в С++ в зависимости от типа
Сообщение28.08.2018, 16:36 
aa_dav
EtCetera
Спасибо, не знал и почему-то так решил.

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

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

 
 
 
 Re: Перегрузка в С++ в зависимости от типа
Сообщение28.08.2018, 20:26 

(Оффтоп)

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

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

 
 
 
 Re: Перегрузка в С++ в зависимости от типа
Сообщение28.08.2018, 21:37 
warlock66613 в сообщении #1335132 писал(а):
Я неоднократно писал ручную конвертацию из UTF-8 в CP1251 и обратно и небоскрёбов как-то не заметил.
Возможно Вам повезло или Вы делали ограниченную поддержку. Например не учитывали возможность появления символов (типа Ё и Й) в NFD форме или со знаками ударений или с указанием начертания или неправильно (с лишними байтами) закодированных UTF8, да много чего может попасться. Я честное преобразование так и не собрался с духом писать, как окинул взором это море вариантов, так руки и опустились и ограничился использованием в устройствах одной CP1251 кодировки и преобразованием через кажется WideCharToMultiByte из WinAPI и пусть винда сама мучается. Или тупо проигнорировал все эти варианты и реализовал лишь простейший, с ним то проблем нет, Вы правы.
Возможно я излишне усложняю себе задачу.

 
 
 
 Re: Перегрузка в С++ в зависимости от типа
Сообщение28.08.2018, 22:12 
Аватара пользователя
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 
Аватара пользователя
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 
Аватара пользователя
Я просто скромно пискну, что в некоторых языках само понятие капитализации не имеет смысла, зато с текстом бывают другие преобразования.

В простом и незамысловатом корейском языке слово 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 
Добавлю всё же и сюда что я выше имел в виду под торможением и сломом быстрых алгоритмов поиска подстрок. Многие из них (типа Бойера-Мура) основаны на уменьшении количества сравнений с каждого символа входного текста (как для Кнута-Морриса-Пратта) до каждого n-го (в идеале n - длина искомой подстроки) до нахождения частичного совпадения (после нахождения которого остаток уже проверяется посимвольно). И тут критично что смещение следующего проверяемого символа вычисляется в терминах/единицах символов, а не байтов/слов, и преобразовать это смещение к количеству байтов во входном тексте для символов нефиксированной длины нереально без посимвольного просмотра текста (может и есть какие-то эвристики, не в курсе, но не думаю что кардинальные), от чего собственно и уходили, т.е. такой "быстрый" алгоритм будет медленнее посимвольного просмотра текста (распознающим автоматом). А без преобразования можно легко попасть в середину символа или не в тот символ и без принятия специальных мер алгоритм поиска сломается.
Т.е. такие алгоритмы перестают быть хорошими для любого алфавита с непостоянной длиной символов, не только unicode или тем паче utf8.

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

 
 
 
 Re: Юникод и работа с ним
Сообщение29.08.2018, 20:15 
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 
Аватара пользователя
Dmitriy40 в сообщении #1335365 писал(а):
Внимание вопрос: по какому байтовому смещению нужно взять code point в кодировке UTF32 чтобы попасть гарантированно на 4-й символ произвольного входного текста в Unicode (в UTF32 разумеется) с кучей ударений, умляутов, выбором направления письма, и прочими непечатными символами среди первых трёх символов текста?
А зачем нам тут графема? Давайте искать 4й code point. Его адрес в UTF32 найти могу даже я.
Т.е. давайте искать подстроку в смысле code point, а не графем. В случае UTF8 - можно даже искать подстроку в смысле байт (хотя если шаблон и текст - корректные UTF8, то вхождения шаблона в текст как байтовой строки и как последовательности code point совпадают).

 
 
 [ Сообщений: 29 ]  На страницу 1, 2  След.


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group