LINUX.ORG.RU

Написал статью «Как жить если у вас юникод»

 ,


5

4

Собственно, сабж. Статья про то самое, что мы с Eddy_Em не могли осилить в прежние времена. В этом году я это, внезапно, осилил. Ну и написал статью.

https://saahriktu.ru/pdf/kak_jit_esli_u_vas_yunikod.pdf

★★★★★

где этот @hateyoufeel и почему я должен выполнять его обязанности?

итак, стандарты.

  1. спецификация POSIX глаголит
For the new process image, the equivalent of:

setlocale(LC_ALL, "C")

shall be executed at start-up.

ей вторит C11 §7.11.1.1 The setlocale function

At program startup, the equivalent of

setlocale(LC_ALL, "C");

is executed.

хотите системную? setlocale(LC_ALL, "");

нужна ли вам (системная) локаль или достаточно дефолтной?

а это смотря чего вы хотите. просто вывести букафки на экран? https://godbolt.org/z/oEqcGP1eM

а зачем тогда нужно устанавливать локаль? например затем

double price;
char buf[SZ];
while ( ... )     // processing the German invoice
{
   setlocale(LC_ALL, "en_US");
   fscanf(priceFile,"%lf",&price);
   // convert $ to DM according to the current exchange rate
   setlocale(LC_ALL,"de_DE");
   strfmon(buf,SZ,"%n",price);
   fprintf(invoiceFile,"%s",buf);
}
  1. стандарт Unicode 4.0 говорит нам (цитирую):

ANSI/ISO C оставляет семантику широких символов на усмотрение конкретной реализации

размер типа wchar_t определяется компилятором, вплоть до минимальных 8 бит. Соответственно, приложения, которым требуется сохранять переносимость на различных C и C++ компиляторах, не должны использовать wchar_t для хранения Unicode-текста. Тип wchar_t предназначен для хранения широких символов в том виде, в котором их понимают конкретные компиляторы, и это может не соответствовать Юникоду

всё, можно дальше растекаться.

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

А через десяток лет выяснилось, что wchar_t — это неадекватный способ хранения юникода и обычный char с этим прекрасно справляется, если используется кодировка юникода UTF-8.

wchar_t конечно не является золотой пулей, но в некоторых задачах не заменим (для меня по крайне мере и автора статьи, да и разработчики python3 его во всю пользуют).

Вы ещё пожалуйтесь, что ваша программа на C не работает как положено на БК0010. Нужно современными реалиями жить, а не тащить на горбу всякий шлак из прошлого.

Чтобы Си и библиотеки для работы с текстом (про utf-8 я не слова не сказал) работали на разных системах, а не только linux вызов setlocale() оставили на программиста, а уже он решает нужна ли сортировка по алфавиту и регулярки завязаные на локаль.

s-warus ★★★
()

Несмотря на то, что такие языки программирования как Python, Ruby и Free Pascal хорошо поддерживают юникод при работе с ним могут возникать трудности у программистов на C и C++.

Шел суровый 2023 год. Программисты C/C++ все так же страдали, выплясывая до кровавых мозолей над строками, которые на самом деле массивы, но массивы из символов, но символы - это не символы а байты, но байты - это не коды, потому что код символа многобайтовый. Вот так легко и просто можно работать с Unicode строками в самих прогрессивных языках, которые придумал человек.

PS: После «юникод» забыта запятая.

Xintrea ★★★★★
()

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

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

Так было в ISO 10646, но абсурдность такого подхода стала настолько очевидна, что от в Юникоде от нее отказались.

А в Plan 9 не отказались: там руна = символ. И, соответственно, строка = массив символов.

monk ★★★★★
()
Ответ на: комментарий от s-warus

wchar_t конечно не является золотой пулей, но в некоторых задачах не заменим

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

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

Напоминаешь одного, использует профессионально web-фреймворк, но что такое css и html - тёмный лес - это тёмное легаси.
То что, ты не встречал проблем, нипочём не говорит.
Инструменты использующие wchar_t изолируют тебя от его использования.
В малоизвестной и протухшей для тебя библиотеке Boost работа с интерциональными символами, идёт с помощью широких (UChar32) символов, для utf-8 есть только конвертация в UChar32 и обратно, что может немного тебя убедит, что в некоторых задачах utf-8 крайне не удобен.

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

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

Они как раз продвигают UTF-8: https://www.boost.org/doc/libs/1_83_0/libs/locale/doc/html/recommendations_and_myths.html

monk ★★★★★
()
Ответ на: комментарий от s-warus

библиотеке Boost работа с интерциональными символами, идёт с помощью широких (UChar32) символов

boost::locale::generator gen;
using namespace boost::locale::boundary;
std::string text="生きるか死ぬか、それが問題だ。";
ssegment_index map(word,text.begin(),text.end(),gen("ja_JP.UTF-8"));
for(ssegment_index::iterator it=map.begin(),e=map.end();it!=e;++it) {
    std::cout << "Segment " << *it << " contains: ";
    if(it->rule() & word_none)
        std::cout << "white space or punctuation marks ";
    if(it->rule() & word_kana)
        std::cout << "kana characters ";
    if(it->rule() & word_ideo)
        std::cout << "ideographic characters";
    std::cout<< std::endl;
}

Would print:

Segment 生 contains: ideographic characters
Segment きるか contains: kana characters
Segment 死 contains: ideographic characters
Segment ぬか contains: kana characters
Segment 、 contains: white space or punctuation marks
Segment それが contains: kana characters
Segment 問題 contains: ideographic characters
Segment だ contains: kana characters
Segment 。 contains: white space or punctuation marks

Где?

monk ★★★★★
()
Ответ на: комментарий от s-warus

Напоминаешь одного, использует профессионально web-фреймворк, но что такое css и html - тёмный лес - это тёмное легаси.

Не надо свой синдром самозванца на меня проецировать.

Не веришь мне — так вон Тонский буквально сегодня ещё разок проехался по могиле UTF-16: https://tonsky.me/blog/unicode

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

Тонский и по самому юникоду неплохо проехался. И про трактовку текста в зависимости от настроек ОС и про неограниченное число компонентов в графеме. А всё потому, что разработчикам Юникода очень хотелось сэкономить номера символов. Теперь символов ещё около 800000 свободно, зато работа с юникодом везде страдает.

И сделать уже практически ничего нельзя. Проклятие совместимости.

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

Не веришь мне — так вон Тонский буквально сегодня ещё разок проехался по могиле UTF-16: https://tonsky.me/blog/unicode

Этот блог был опубликован в 2015 году «The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!) - Joel on Software»".
https://waksoft.susu.ru/2015/04/01/the-absolute-minimum-every-software-develo...

Forum0888
()
Последнее исправление: Forum0888 (всего исправлений: 2)
Ответ на: комментарий от Forum0888

Отец, разуй глаза, «блог» Спольски был опубликован в 2003 году: https://joelonsoftware.com/2003/10/08/the-absolute-minimum-every-software-developer-absolutely-positively-must-know-about-unicode-and-character-sets-no-excuses , а я привёл ссылку не на него, а на запись в блоге Никиты Прокопова, которая была опубликована четыре дня назад и, хоть и ссылается на статью Спольски, гораздо глубже описывает современные реалии.

lockie
()
14 декабря 2023 г.

Не в силах выдержать безграмотности автора топика, я взял на себя труд записать бесплатный открытый урок на полтора часа по теме «Unicode в C» в рамках онлайн-платформы Otus, на которой работаю: https://www.youtube.com/watch?v=YsiOpbwHocE

lockie
()
Последнее исправление: lockie (всего исправлений: 1)
Ответ на: комментарий от lockie

Представим, что у меня приложение c ограниченным пользовательским вводом, поэтому расширенный набор влазит в wchar_t, и мне достаточно wc*. В этом случае утверждение в вашем ролике о том, что setlocale не нужно, превратит программу в тыкву.

level1 ★★
()

«Как жить если у вас юникод»

Да также как со спидом. Принимать таблетки, принять факт, что эта зараза уже навсегда и из организма никуда уже не выведется как юникод из гну/бенилюкса.

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

Что такое «ограниченный пользовательский ввод»? Такого понятия нет ни в стандарте C, ни в стандарте Unicode. Что вам мешает конвертировать средствами iconv то, что приходит из других источников в странных кодировках в UTF8 и работать внутри программы с UTF8?

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

Такого понятия нет ни в стандарте C, ни в стандарте Unicode.

А это обычный русский язык за рамками стандарта С.

Что такое «ограниченный пользовательский ввод»?

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

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

UTF8 не может быть «ограничен кодпоинтами в два байта», он может с одинаковой лёгкостью хранить кодпоинты длиной от одного до четырёх байт, потому что это кодировка с переменной длиной. Если почему-то в вашем конкретном приложении вы уверены, что кодпоинты выше определённого номера, например, эмодзи, встречаться не будут, то ничего не мешает хранить их в массивах из char закодированными в UTF8, и не понадобятся костыли и пляски с бубнами вроде wchar_t и setlocale.

lockie
()