Re: C++ и UTF8
От: okman Беларусь https://searchinform.ru/
Дата: 27.10.11 11:59
Оценка: -3 :))) :))
Здравствуйте, Аноним, Вы писали:

А>Подскажите пожалуйста, как в С++ работать со строками в кодировке 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 и
использовать те строковые типы, которые они предлагают.
Re[2]: C++ и UTF8
От: okman Беларусь https://searchinform.ru/
Дата: 27.10.11 12:07
Оценка: +1 :))
Та-а-ак, с чем господин uzhas не согласен (если что, мне оценки по боку) ?
Re[2]: C++ и UTF8
От: Pavel Dvorkin Россия  
Дата: 27.10.11 12:11
Оценка:
Здравствуйте, dilmah, Вы писали:


А>>(требуется стандартный набор строковых функций — strcmp(), strcat(), strcpy()... )


D>strcat, strcpy работают без изменений


А strlen ? Результат-то она вернет, да только что он означает ?

Как насчет strstr ?

Как насчет p++ и доступа к строке с любого места ранее '\0' ?

В общем, не надо применять инструмент для работы с однобайтовой кодировкой к UTF-8.
With best regards
Pavel Dvorkin
Re[2]: C++ и UTF8
От: uzhas Ниоткуда  
Дата: 27.10.11 12:12
Оценка: -1
Здравствуйте, okman, Вы писали:


O>Правильный подход тут уже указали — нужно подключать сторонние библиотеки вроде ICU и

O>использовать те строковые типы, которые они предлагают.
есть у меня опыт работы с "правильным" подходом
так вот выбросили его через два года, ибо устали: тормоза в рантайме и депенд на ICU (как следствие тормоза компиляции, усложнение инсталяторов), а выигрыша ноль
заменили на std::string (UTF8), std::wstring (win)\ std::basic_string<short> (linux) (UTF16) и стало замечательно
софт локализован на 14 языков (включая азиатские), полет нормальный
НО! это касается серверных приложений

ГУЙ, которому нужно переводить слова по строкам, лейаут прорабатывать остался на ICU (хотя в кишках и с std:(w)string работает)
Re[4]: C++ и UTF8
От: gegMOPO4  
Дата: 27.10.11 12:13
Оценка: +3 -1
Здравствуйте, sidorov18, Вы писали:
S>Здравствуйте, gegMOPO4, Вы писали:
MOP>>Здравствуйте, sidorov18, Вы писали:
S>>>Может сразу в UTF-16 переводить?
MOP>>UTF-16 во всех смыслах хуже UTF-8.
S>
S>Скажите хоть пару.

Несовместимость с ASCII, непереносимость, проблема 0-го байта, больший расход памяти (и времени) в большинстве случаев…

А вот чем UTF-16 лучше UTF-8? Ничем. Сохраняет недостатки UTF-8 и добавляет свои.
Re[5]: C++ и UTF8
От: uzhas Ниоткуда  
Дата: 27.10.11 12:21
Оценка:
Здравствуйте, gegMOPO4, Вы писали:

MOP>А вот чем UTF-16 лучше UTF-8? Ничем. Сохраняет недостатки UTF-8 и добавляет свои.

ну он лучше, чем UTF-8 тем, что уменьшает вероятность размазывания юникодного символа по нескольким байтам
идеальным в этом плане является UTF-32
Re[3]: C++ и UTF8
От: dilmah США  
Дата: 27.10.11 12:21
Оценка:
PD>Как насчет strstr ?

и что же с strstr?

Первый байт любого символа всегда отличается от непервого байта. Кроме того если кол-во байтов в символах отличается то их первый байт тоже отличается.
Re[3]: C++ и UTF8
От: okman Беларусь https://searchinform.ru/
Дата: 27.10.11 12:23
Оценка:
Здравствуйте, uzhas, Вы писали:

U>заменили на std::string (UTF8)


Вот тут, пожалуйста, поподробнее, ибо:

#include <iostream>
#include <string>

int main()
{
    unsigned char Utf8EncodedText[] =
    {
        0xD0, 0x9F, 0xD1, 0x80, 0xD0, 0xB8, 0xD0, 0xB2,
        0xD0, 0xB5, 0xD1, 0x82, 0x2C, 0x20, 0xD0, 0xBC,
        0xD0, 0xB8, 0xD1, 0x80, 0x21,
        0x00
    }; // Привет, мир!

    std::string TestString = (char *)&Utf8EncodedText[0];
    std::cout << "Length is " << TestString.length() << std::endl;

    return 0;
}

>Length is 21

Re[6]: C++ и UTF8
От: gegMOPO4  
Дата: 27.10.11 12:24
Оценка:
Здравствуйте, sidorov18, Вы писали:
S>Зато все винапи работает с UTF-16.

А не с UCS2?

S>+ если понадобится узнать количество символов в строке или доступ по индексу — моментально вылезут удобства UTF-16.


Какие удобства? Что для UTF-8, что для UTF-16 доступ по индексу — O(n). Только в последнем случае обычно нужно обработать больше байт.

Вот поэтому доступ по индексу при работе с текстом — плохая идея.
Re[7]: C++ и UTF8
От: uzhas Ниоткуда  
Дата: 27.10.11 12:25
Оценка:
Здравствуйте, gegMOPO4, Вы писали:

MOP>А не с UCS2?

это было в самых первых виндах
далее на UTF-16 все же перешли
Re[4]: C++ и UTF8
От: uzhas Ниоткуда  
Дата: 27.10.11 12:28
Оценка: 1 (1) +1
Здравствуйте, okman, Вы писали:

O>

>Length is 21

ну неинтересно серверу знать сколько там юникодных символов
ему достаточно знать сколько байтов сжирает строка
Re[6]: C++ и UTF8
От: gegMOPO4  
Дата: 27.10.11 12:31
Оценка:
Здравствуйте, uzhas, Вы писали:
U>Здравствуйте, gegMOPO4, Вы писали:
MOP>>А вот чем UTF-16 лучше UTF-8? Ничем. Сохраняет недостатки UTF-8 и добавляет свои.
U>ну он лучше, чем UTF-8 тем, что уменьшает вероятность размазывания юникодного символа по нескольким байтам

Да неужели?! В UTF-8 128 символа (в число которых входят наиболее частые) кодируются одним байтом. В UTF-16 каждый символ размазывается по нескольким байтам.

U>идеальным в этом плане является UTF-32


Не идеал, но у него есть свои достоинства.
Re[6]: C++ и UTF8
От: watch-maker  
Дата: 27.10.11 12:34
Оценка: +3
Здравствуйте, 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 он взял избыточные требования к памяти. Весьма сомнительное достижение.
Re[3]: C++ и UTF8
От: okman Беларусь https://searchinform.ru/
Дата: 27.10.11 12:34
Оценка: -2 :)
Здравствуйте, 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) и пользоваться ей ?
И при этом ссылаетесь на опыт разработки серверного приложения, где такие "мелочи", как длина
строки, несущественны ? Не могу согласиться с такой точкой зрения.
Re[7]: C++ и UTF8
От: uzhas Ниоткуда  
Дата: 27.10.11 12:46
Оценка:
Здравствуйте, gegMOPO4, Вы писали:

MOP>Да неужели?! В UTF-8 128 символа (в число которых входят наиболее частые) кодируются одним байтом. В UTF-16 каждый символ размазывается по нескольким байтам.

имелось в виду другое: std::basic_string<wchar_t> под виндой подходит для хранения UTF16, в таком случае в один wchar_t влезает бОльше инфы и размазать юникодные символ по двум wchar_t становится сложнее =)
Re[2]: C++ и UTF8
От: gegMOPO4  
Дата: 27.10.11 12:51
Оценка: +3
Здравствуйте, 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. Во многих случаях можно обойтись без.
Re[4]: C++ и UTF8
От: uzhas Ниоткуда  
Дата: 27.10.11 12:51
Оценка: 1 (1)
Здравствуйте, okman, Вы писали:

O>написать специализацию basic_string для типа

заметил, что беседа крайне непродуктивна
Re[7]: C++ и UTF8
От: sidorov18 США  
Дата: 27.10.11 12:51
Оценка:
Здравствуйте, watch-maker, Вы писали:

WM>Здравствуйте, sidorov18, Вы писали:


S>>+ если понадобится узнать количество символов в строке или доступ по индексу — моментально вылезут удобства UTF-16.


WM>Это какие же? С UTF-16 при решении данных задач работать так же неудобно как и с UTF-8.

WM>Вся разница лишь в том, что в UTF-8 один символ может занимать 1,2,3,4 байта, а в в UTF-16 соответственно 2 или 4 байта.

Для какого языка? Каких нибудь китайских диалектов?
Re[8]: C++ и UTF8
От: gegMOPO4  
Дата: 27.10.11 12:55
Оценка:
Здравствуйте, uzhas, Вы писали:
U>Здравствуйте, gegMOPO4, Вы писали:
MOP>>А не с UCS2?
U>это было в самых первых виндах
U>далее на UTF-16 все же перешли

Т.е. вернулись к тому, из-за чего отказались от UTF-8. Где здесь смайл иронии?
Re[5]: C++ и UTF8
От: sidorov18 США  
Дата: 27.10.11 12:57
Оценка: 1 (1) +1
Здравствуйте, 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.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.