Здравствуйте, Аноним, Вы писали:
А>Подскажите пожалуйста, как в С++ работать со строками в кодировке UTF-8 ? А>(требуется стандартный набор строковых функций — strcmp(), strcat(), strcpy()... )
Вижу, тут у вас плюсы-минусы раздают, дай-ка я себе что-нибудь отгребу...
Нельзя использовать строки std:(w)string для работы с UTF-8.
Потому что шаблонный тип для basic_string — это char и wchar_t, длина которого фиксирована.
В Visual C++ это 1 и 2 байта соответственно. А UTF-8 — многобайтовая кодировка, символ в ней
может быть представлен как одним байтом, так и четырьмя.
Поэтому ни std::string::length, ни использование строковых итераторов и алгоритмов,
не будет давать нужный результат. Кто не верит, может попробовать считать из файла в UTF-8
какую-нибудь строчку в кириллице, а потом средствами std:(w)string попробовать поработать с ней.
Какое-то подмножество строковых функций будет работать, остальные — нет.
Правильный подход тут уже указали — нужно подключать сторонние библиотеки вроде ICU и
использовать те строковые типы, которые они предлагают.
O>Правильный подход тут уже указали — нужно подключать сторонние библиотеки вроде ICU и O>использовать те строковые типы, которые они предлагают.
есть у меня опыт работы с "правильным" подходом
так вот выбросили его через два года, ибо устали: тормоза в рантайме и депенд на ICU (как следствие тормоза компиляции, усложнение инсталяторов), а выигрыша ноль
заменили на std::string (UTF8), std::wstring (win)\ std::basic_string<short> (linux) (UTF16) и стало замечательно
софт локализован на 14 языков (включая азиатские), полет нормальный
НО! это касается серверных приложений
ГУЙ, которому нужно переводить слова по строкам, лейаут прорабатывать остался на ICU (хотя в кишках и с std:(w)string работает)
Здравствуйте, sidorov18, Вы писали: S>Здравствуйте, gegMOPO4, Вы писали: MOP>>Здравствуйте, sidorov18, Вы писали: S>>>Может сразу в UTF-16 переводить? MOP>>UTF-16 во всех смыслах хуже UTF-8. S> S>Скажите хоть пару.
Несовместимость с ASCII, непереносимость, проблема 0-го байта, больший расход памяти (и времени) в большинстве случаев…
А вот чем UTF-16 лучше UTF-8? Ничем. Сохраняет недостатки UTF-8 и добавляет свои.
Здравствуйте, gegMOPO4, Вы писали:
MOP>А вот чем UTF-16 лучше UTF-8? Ничем. Сохраняет недостатки UTF-8 и добавляет свои.
ну он лучше, чем UTF-8 тем, что уменьшает вероятность размазывания юникодного символа по нескольким байтам
идеальным в этом плане является UTF-32
Первый байт любого символа всегда отличается от непервого байта. Кроме того если кол-во байтов в символах отличается то их первый байт тоже отличается.
Здравствуйте, uzhas, Вы писали: U>Здравствуйте, gegMOPO4, Вы писали: MOP>>А вот чем UTF-16 лучше UTF-8? Ничем. Сохраняет недостатки UTF-8 и добавляет свои. U>ну он лучше, чем UTF-8 тем, что уменьшает вероятность размазывания юникодного символа по нескольким байтам
Да неужели?! В UTF-8 128 символа (в число которых входят наиболее частые) кодируются одним байтом. В UTF-16 каждый символ размазывается по нескольким байтам.
U>идеальным в этом плане является UTF-32
Здравствуйте, sidorov18, Вы писали:
S>+ если понадобится узнать количество символов в строке или доступ по индексу — моментально вылезут удобства UTF-16.
Это какие же? С UTF-16 при решении данных задач работать так же неудобно как и с UTF-8.
Вся разница лишь в том, что в UTF-8 один символ может занимать 1,2,3,4 байта, а в в UTF-16 соответственно 2 или 4 байта.
То есть если вам нужно посчитать число символов в строке, то всё равно придётся бегать и анализировать каждый байт в обоих этих представлениях.
Если вам нужно обращаться к символу по индексу, то так же придётся бежать с начала строки и анализировать байты (ну или двухбайтовые позиции, что в данном случае не важно), суммируя количество найденных символов, что делается так же как и в UTF-8.
Вообще, в юникоде были только два представления, которые позволяют адресовать символ непосредственно по его номеру: UTF-32 и UCS-2. Но второе представление — это артефакт оставшийся с первых версий юникода, и сейчас оно не поддерживается, и поэтому остаётся только UTF-32.
И уж если говорить об удобствах, то UTF-16 — это очень неудобный способ кодирования символов, который взял и объединил недостатки UTF-8 и UTF-32. От UTF-8 он взял переменную длинну кодирования символов (что не позволяет быстро адресовать символы по индексу), а от UTF-32 он взял избыточные требования к памяти. Весьма сомнительное достижение.
Здравствуйте, uzhas, Вы писали:
U>есть у меня опыт работы с "правильным" подходом U>так вот выбросили его через два года, ибо устали: тормоза в рантайме и депенд на ICU (как следствие тормоза компиляции, усложнение инсталяторов), а выигрыша ноль U>заменили на std::string (UTF8), std::wstring (win)\ std::basic_string<short> (linux) (UTF16) и стало замечательно
То есть, Вы предлагаете человеку, который хочет работать в C++ с UTF-8, не полагаться на
библиотеки вроде ICU или iconv, а написать специализацию basic_string для типа, достаточного по
размеру, чтобы вмещать любые символы UTF-8 (видимо, unsigned int) и пользоваться ей ?
И при этом ссылаетесь на опыт разработки серверного приложения, где такие "мелочи", как длина
строки, несущественны ? Не могу согласиться с такой точкой зрения.
Здравствуйте, gegMOPO4, Вы писали:
MOP>Да неужели?! В UTF-8 128 символа (в число которых входят наиболее частые) кодируются одним байтом. В UTF-16 каждый символ размазывается по нескольким байтам.
имелось в виду другое: std::basic_string<wchar_t> под виндой подходит для хранения UTF16, в таком случае в один wchar_t влезает бОльше инфы и размазать юникодные символ по двум wchar_t становится сложнее =)
Здравствуйте, okman, Вы писали: O>Нельзя использовать строки std:(w)string для работы с UTF-8. O>Потому что шаблонный тип для basic_string — это char и wchar_t, длина которого фиксирована. O>В Visual C++ это 1 и 2 байта соответственно. А UTF-8 — многобайтовая кодировка, символ в ней O>может быть представлен как одним байтом, так и четырьмя.
Ну и что? Поскольку UTF-8 совместима с ASCII и обладает ещё рядом замечательных свойств, ничто не мешает использовать std::string как контейнер. А наличие ряда специализированных функций для работы со строками делает его предпочтительнее std::vector<char>.
O>Поэтому ни std::string::length, ни использование строковых итераторов и алгоритмов, O>не будет давать нужный результат.
Какой результат вам нужен? Результат std::string::length — A count of the number of char-like objects (т.е. char в данном случае) currently in the string. Иными словами — количество байт в представлении UTF-8.
O> Кто не верит, может попробовать считать из файла в UTF-8 O>какую-нибудь строчку в кириллице, а потом средствами std:(w)string попробовать поработать с ней. O>Какое-то подмножество строковых функций будет работать, остальные — нет.
Да практически все будут работать. Какие не? Нужно только помнить, что std::string::length возвращает не количество символов, а pos — смещение, а не номер символа.
Фактически единственная операция, где std::string недостаточно — обрезка строки по заданному количеству символов.
O>Правильный подход тут уже указали — нужно подключать сторонние библиотеки вроде ICU и O>использовать те строковые типы, которые они предлагают.
Только тогда, когда вам действительно нужны возможности ICU. Во многих случаях можно обойтись без.
Здравствуйте, watch-maker, Вы писали:
WM>Здравствуйте, sidorov18, Вы писали:
S>>+ если понадобится узнать количество символов в строке или доступ по индексу — моментально вылезут удобства UTF-16.
WM>Это какие же? С UTF-16 при решении данных задач работать так же неудобно как и с UTF-8. WM>Вся разница лишь в том, что в UTF-8 один символ может занимать 1,2,3,4 байта, а в в UTF-16 соответственно 2 или 4 байта.
Для какого языка? Каких нибудь китайских диалектов?
Здравствуйте, uzhas, Вы писали: U>Здравствуйте, gegMOPO4, Вы писали: MOP>>А не с UCS2? U>это было в самых первых виндах U>далее на UTF-16 все же перешли
Т.е. вернулись к тому, из-за чего отказались от UTF-8. Где здесь смайл иронии?
Здравствуйте, gegMOPO4, Вы писали:
MOP>Здравствуйте, sidorov18, Вы писали: S>>Здравствуйте, gegMOPO4, Вы писали: MOP>>>Здравствуйте, sidorov18, Вы писали: S>>>>Может сразу в UTF-16 переводить? MOP>>>UTF-16 во всех смыслах хуже UTF-8. S>> S>>Скажите хоть пару.
MOP>Несовместимость с ASCII, непереносимость, проблема 0-го байта, больший расход памяти (и времени) в большинстве случаев…
Если вы работаете с COM(который нужно, что бы из скриптов вызывался), к примеру, — UTF-8 будет таким же несовместимым. Здесь вопрос в окружении.
Но конвертирование, в большинстве случаев, проходит очень быстро, только если вопрос не упирается в мегабайт(ы) строк.
Расход памяти тоже в большинстве случаев незаметен.
И что за проблема 0-го байта?
MOP>А вот чем UTF-16 лучше UTF-8? Ничем. Сохраняет недостатки UTF-8 и добавляет свои.
в соседней ветке уточняем по поводу доступа по индексу.
Но проблема совместимости так же актуальна и для UTF-8. Здесь вопрос окружения, а не ситуация, если бы
везде был UTF-8.