LINUX.ORG.RU

wchar_t и юникод

 


0

3

дорогие всё никак не исчезающие любители приравнивать wchar к «юникоду»:

1) приведите выдержку из стандарта вашей любимой сишечки где wchar приравнен к «юникоду»

2) потрудитесь объяснить что такое «юникод». Вы вообще в курсе что это название стандарта и что способов кодирования юникода легко и непринуждённо наберётся с десяток в любом варианте применения?

Ответ на: комментарий от dzidzitop

что значит «легко» и при чём тут портируемость? в С нет понятия «сортировка». пиши библиотеку или используй уже существующие библиотеки.

в общем, есть те, кто пишет работающий код, а есть те, кому яйца мешают.

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

вместо кода сортировки

#include <ios>
#include <deque>
#include <locale>
#include <string>
#include <iostream>
#include <iterator>
#include <algorithm>

int main(int argc, char*[]) try
{
    std::locale::global(std::locale(""));
    std::wcin.imbue(std::locale());
    std::wcout.imbue(std::locale());
    std::wcin.exceptions(std::ios_base::badbit);
    std::wcout.exceptions(std::ios_base::badbit);

    std::deque<std::wstring> text(1);
    while (std::getline(std::wcin,text.back())) text.emplace_back();

    std::sort(std::begin(text),std::end(text),std::locale(""));

    std::move(std::begin(text),std::end(text),
              std::ostream_iterator<std::wstring,wchar_t>(std::wcout,L"\n"));
    std::wcout<<std::flush;
}
catch (...) { throw; }

helloworld, конечно, но сортировать должен согласно заданной локали. Локаль, правда, задаётся так: LC_ALL=xxx <run command>, но самый частый случай - использование умолчательной локали(т. е. даже LC_ALL выставлять не нужно)

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

Ну вот хоть кто-то родил конкретику для самой простой задачи. Код, вероятно, работает при исправном компиляторе. Поздравляю!

А как сделать сортировку на системе, в которой нет локали данного языка?
А как сделать регистронезависимую сортировку?
А как подсчитать количество слов, начинающихся на каждую букву алфавита данного языка?

Это всё ещё тривиальные задачи, если пользоваться, например, utf-8 и знанием о правилах нужного языка. А как их решать с wchar_t?

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

А как сделать сортировку на системе, в которой нет локали данного языка?

Разумеется, в отсутствие нужной локали подобный код не сработает(ещё вспомнинаются нестандартизованные имена локалей, в результате чего единственным переносимым вариантом является user-preffered locale). Но здесь вопрос сродни следующему: отработает ли сценарий на языке X в отсутствие в системе интерпретатора для него? Вопрос риторический. Точно также локали являются реализацией некого функционала, и, если мы хотим этим функционалом воспользоваться, он должен в системе присутствовать. Зависимость здесь тоньше, но она есть.

А как сделать регистронезависимую сортировку?

Удобного решения здесь нет, т. е. суть в том, чтобы где-нибудь(дополнительное поле данных для сортировки, переопределённый метод collate::compare() etc) руками приводить ключи в, скажем, нижний регистр. Кстати, не определяется ли регистро(не)зависимость правилами конкретного языка?

А как подсчитать количество слов, начинающихся на каждую букву алфавита данного языка?

Честно говоря, не вижу особых трудностей. Есть std::isalpha() и std::tolower(), отличие лишь в использовании фацетов нужным образом сконструированного std::locale вместо привычных операторов отношения и функций типа strcmp.

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

  • древность стандартных интерфейсов и отсутствие корректирующих изменений(пример: std::codecvt::length() использует int в качестве возвращаемого типа)
  • слабая поддержка реализациями(на некоторых системах даже конструирование user-preffered локали кидает исключение и хрен что с этим можно поделать)

Может в c++3x сделают нормально :-)

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

Ну ok, на вкус и цвет, как говориться...

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

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

При этом если забить на wchar_t и пользоваться юникодом, то проблем никаких нет, кроме как понять как, собственно, пользоваться юникодом.

Я к чему, собственно говоря, веду - как полько появляется необходимость работать с конкретными буквами (символами), то wchar_t превращается в тыкву без рук и без ног. Потому что не поддерживает ни одну конкретную букву. Это если не обращать внимания, что способ кодирования строк wchar_t тоже не определён в общем случае.

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

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

towlower() не работает, если что. К тому же он ничего не знает о языковом контексте. А работает (абсолютно неправильно) типа с «общечеловеческим языком». При том, что в разных языках разные правила и разные формы символов (т.е. разные кодпойнты, иногда несколько) в разных регистрах.

Only 1:1 character mapping can be performed by this function, e.g. the Greek uppercase letter 'Σ' has two lowercase forms, depending on the position in a word: 'σ' and 'ς'. A call to std::towlower cannot be used to obtain the correct lowercase form in this case.

а если бы и работал даже, представим, то ignore-case сортировка не эквивалентна сортировке lower-case. К тому же, всё, что не принадлежит алфавиту конкретного языка, с точки зрения языка не имеет регистра и language-aware tolower должен оставлять все такие символы без изменения.

масштаб трагедии всё ещё не очевиден?

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

гласные буквы

Облом, причём полный. А подобное вообще предоставляется какм-либо средством? Беглый гуглинг по доке boost.locale и ICU ничего не дал. Я к тому, что разделение букв на гласные и согласные может не обобщаться простым образом на все языки(один проблематичный момент по интернационализации, который навёл на эту мысль)

towlower() не работает, если что. К тому же он ничего не знает о языковом контексте

Я имел ввиду template<typename T> std::tolower(T, const std::locale&).

ignore-case сортировка не эквивалентна сортировке lower-case

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

всё, что не принадлежит алфавиту конкретного языка, с точки зрения языка не имеет регистра и language-aware tolower должен оставлять все такие символы без изменения

Утверждать не возьмусь, но думаю, при отсутствии ошибок в реализации стандартной библиотеки, оно так и есть. std::tolower() с «C» локалью кириллицу не трогает, при этом с локалью «ru_RU» переводит в нижний регистр

композитные символы

Only 1:1 character mapping can be performed

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

масштаб трагедии всё ещё не очевиден?

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

Deleted
()
Ответ на: комментарий от deep-purple

Я всегда писал, что C++ - говно. Тут ничего нового.

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