Кодировки
Внимание! Это довольно старый топик, посты в него не попадут в новые, и их никто не увидит. Пишите пост, если хотите просто дополнить топик, а чтобы задать новый вопрос — начните новый.
Внимание! Это довольно старый топик, посты в него не попадут в новые, и их никто не увидит. Пишите пост, если хотите просто дополнить топик, а чтобы задать новый вопрос — начните новый.
Как надо работать с кодировками текста в свете стандарта С++17? Интересует в первую очередь преобразование кириллицы между cp-1251 и utf-8. Но также интересен и общий случай.
В этой теме на форуме что-то подобное обсуждается, но этот код под MSVC++ под стандарт С++17 не компилируется — говорит депрекейтед и советует обратиться к функциям из WinAPI.
А хотелось бы универсальное, кроссплатформенное решение без привлечения сторонних библиотек (т.е. в пределах С++ и STL). Возможно?
Никак. C++ по факту, не поддерживает Unicode, а значит только латиница, всё остальное будет плавать.
MSVC++ не поддерживает C++17, разве что чуть-чуть. std::codecvt_utf8 теперь deprecated, так что не нужно его использовать, если есть расчет на использование более новых компиляторов.
Без сторонних библиотек — только самописный велосипед.
А как же
источник
А как же
char32_t
,chat16_t
,wchar_t
? Первые два, как я понимаю, прямо соответствуют UTF-32 b UTF-16.И еще (драфт стандарта C++17, п. 25.4.1.4):
Вроде как механизм есть. Только как им пользоваться?
Хорошо (в смысле плохо), если невозможно из UTF-8 перекодировать в cp-1251, то как UTF-8 (или другую мультибайтовую кодировку, в которую можно преобразовать UTF-8) вывести на консоль?
Это вообще ни о том. Вот дам строку UTF-8, найди в ней все цифры. Или перекодируй её, например, в UTF-16 BE или в UTF-32 стандартными средствами C++.
В моей библиотеке, например, используется std::vector<uint32_t> для реализации работы с Юникодом. Значит ли это, что vector — это Unicode?
Ну есть тип для символов, а поддержки того, что это за символы — нет. Нет работы с этими символами. Да даже специализации для потоко нет для этих символов. Например, какой-нибудь iswdigit даже с wchar_t без указания локали всё равно не сможет ничего сделать. Да и с локалью тоже хрень получается. Посмотри, например, на Java, Qt, iconv, Glib::ustring, они как раз поддерживают Unicode. Видите разницу?
Он уже устарел. Появился в C++11, устарел в C++17. Замены нет. А получилось так, потому что это фигня лютая.
Консоль Windows не поддерживает добром Unicode. А под Linux, например, терминал, скорее всего, и так будет работать с UTF-8 по дефолту, так что там такой проблемы нет.
Вообще, просто делается один раз инструмент для перекодировки (или берется готовый), который умеет работать с разными кодировками. Работаем в какой-то одной кодировке, а читаем и выводим в той, в которой надо.
Например:
my_utf32string str = get_utf8_line(«path»);//my_utf32string может строить utf32 строку из utf8
//Работаем во всей программе с кодировкой utf32
write_to(std::cout, my_native_string(str));
//my_native_string умеет строить нужную строку для текущей платформы
//ну или явно указывать:
//write_to(std::cout, my_utf8string(str));
Надеюсь, идея понятна. Внутри программы работаем в одной кодировке, а всё сообщение с внешним миром должно настраиваться. Кодировки, локали, и т.д. Назовём это Input Output Layer for Application.
Вот, собственно, и в чем был мой вопрос.
Стоп. Про то, что механизм есть, я говорил, ссылаясь уже на новый стандарт.
Это давно понятно. Вопрос в том, как сделать этот IO Layer средствами C++17. Универсально и переносимо.
Не, вопрос был таков:
Ответ короткий — велосипед.
codecvt_utf8 и codecvt_utf16 устарели.
Там есть еще специализации codecvt для char16_t, char32_t, wchar_t, можете поиграться.
http://ru.cppreference.com/w/cpp/locale/codecvt
А я подожду, когда это будет более хорошо сделано.
Не скажу, что совсем без велосипедов. И даже не скажу, что всё полностью корректно. Но этот код будет работать в 99% случаев. А если поработать напильником, то и в 100%. По крайней мере, ввод из файла строки в UTF-8 и перекодировка в UTF-32 сделан полностью стандартными, не «устаревшими», методами C++17. Жопа случилась, когда дело дошло до манипуляций со строкой типа u32string. Между прочим, стандартной.
1) Без локали работает? )))
2) Какие-нибудь циферки Тай Тхам поддерживает? )))
99% — это про не совсем корректное преобразование utf-32 в wchar_t в функции u32_to_wchar().
Для преобразования utf-8 в utf-32 локаль не нужна. И то, и то — юникод.
Со строками u32string, как и с символами char32_t — жопа :( Я так и не нашёл функций сопоставления (isalpha сотоварищи) для char32_t. А там как бы не все так просто, учитывая компизитные символы. Так что с циферками Тай Тхам в utf-32 обломись :(
А вот с wchar_t вроде как всё нормально, по заверениям MS. Функции
isw*
работают даже без локали. Но есть и версии с локалью:_isw*_l
. Правда не пойму зачем там локаль, если это utf-16 (или ucs-2?). И что-то не нашел точной информации как в wchar_t от MS (который 16-битный) обстоят дела с суррогатными парами. По ходу их там нет.емнип, то так оно и есть.
С char16_t — тоже.
Для преобразования и стандартная библиотека не нужна.
Конвертер utf8 <-> utf32 пишется за несколько часов с нуля, даже если до этого с utf8 никогда не работал (личный опыт это доказывает).
Если только под windows, то зачем стандартная библиотека? Там есть всякие MultiByteToWideChar для преобразований. Под линуксом, например, wchar_t — это utf32, так что там работать будет иначе, и никаких суррогатных пар. Вся соль пользования стандартными средствами — кроссплатформа и гарантия работы. Пока с этим жопа, я предпочитаю иные средства. ICU, например. :)
Согласен. Но это уже свой велосипед, а разговор шел про стандартизированные средства.
Под линуксом тоже не всё так гладко, как хотелось бы. Но получше, чем в винде. Кстати, (1) преобразование utf8 <-> utf32 из STL будет работать (кроссплатформа и гарантия работы) и (2) интересно, циферки Тай Тхам в utf32 будут определяться?
Меня, собственно, заинтересовал вопрос что сделали в С++17 для поддержки Юникода. Оказалось, что нормальной поддержки как не было, так и нет. Печалька.
Пообещали сделать когда-нибудь. Разве этого мало? )))
Вряд ли. Заметьте, в любом уважающем себя фреймворке есть свои строки и функции для работы с ними, потому как в C++ ничего путного для этого нет.
А вот пример с ICU и Тай Тхам:
http://rextester.com/XFB26450
Поразительно, правда? )))
Спасибо, что уделили столько сил моей маленькой проблеме. Некоторые ответы я получил, некоторые вопросы отпали в процессе. Локали, которые работают с потоками — это классно. Никогда бы не додумался, что можно utf8 на лету конвертить в utf32. Но если не из файла? Можно как-то сделать функцию-конвертер на основе codecvt? Или это будет работать только через локаль? Я с этими фасетами-локалями пока до конца так и не разобрался :-\
Огорчило, что с юникодом все равно надо велосипедить. А, между прочим, на носу 2018-й уже.
Пример с ICU — это вообще здорово. Только Ваш код, MasterOfAlteran, на rextester компилится только под g++. Остальные плюсовые компиляторы дают ошибку. Понятно, что мой MSVC++ о ICU — ни сном, ни духом. Следовательно надо качать исходники, компилить и цеплять либу к своему проекту. Очень часто это как из пушки по воробьям. Но заметочку себе поставлю. Спасибо еще раз.
Ну так для гцц и шланга тоже надо цеплять icu, просто под linux с этим проблем нет, как и с кучей других библилиотек. :)