std::wstring vs. ATL::CString vs. _bstr_t ?
От: _Ursus_  
Дата: 13.06.08 16:06
Оценка:
Я тут подумал...
какой класс лучше всего использовать для UNICODE строк:
— std::wstring
— ATL::CString
— _bstr_t
— что-то самописное ?

Если основные требования — скорость и UNICODE.
Чем пользуетесь вы? Только аргументированно, плиз.
Re: std::wstring vs. ATL::CString vs. _bstr_t ?
От: c-smile Канада http://terrainformatica.com
Дата: 13.06.08 23:12
Оценка:
Здравствуйте, _Ursus_, Вы писали:

_U_>Если основные требования — скорость и UNICODE.


Скорость чего конкретно?

std::string это тоже unicode.

там может лежать например utf-8 или например koi8.
И то и то есть способ хранить unicode code points.
Re[2]: std::wstring vs. ATL::CString vs. _bstr_t ?
От: shrecher  
Дата: 14.06.08 00:03
Оценка: -1
Здравствуйте, c-smile, Вы писали:


CS>std::string это тоже unicode.


CS>там может лежать например utf-8 или например koi8.

CS>И то и то есть способ хранить unicode code points.

Я не уверен, что в std::string можно хранить utf-8. Поведение методов типа length и всех от него зависимых не будет учитывыть UTF-8 кодировку и будет возвращать неверные значения.
Re[3]: std::wstring vs. ATL::CString vs. _bstr_t ?
От: c-smile Канада http://terrainformatica.com
Дата: 14.06.08 02:32
Оценка: +1
Здравствуйте, shrecher, Вы писали:

S>Здравствуйте, c-smile, Вы писали:



CS>>std::string это тоже unicode.


CS>>там может лежать например utf-8 или например koi8.

CS>>И то и то есть способ хранить unicode code points.

S>Я не уверен, что в std::string можно хранить utf-8. Поведение методов типа length и всех от него зависимых не будет учитывыть UTF-8 кодировку и будет возвращать неверные значения.


неверные значения чего?

length() в случае std::string даст длину в utf-8 code units — сиречь байтах.
А std::wstring::length() под windows даст длину в utf-16 code units — т.е. words (a.k.a. int16).
Как и _bstr_t/CStringW кстати.

Не забываем что:
1) LPCWSTR это UTF-16 в XP/Vista
2) UNICODE code point это на сегодняшний день 21-bit number.

Если говорить про строки то нужно четко специфицировать набор операций и для чего они будут использоваться.
Если например хранить html/xml текст то utf-8 это оптимальный вариант. Если строки для рисования то в формате
платформы — например utf-16.

Также важен набор операций со строками. Просто хранение текста — это одно. Манипуляции — это другое.
Re: std::wstring vs. ATL::CString vs. _bstr_t ?
От: Zigmar Израиль  
Дата: 14.06.08 03:03
Оценка:
Здравствуйте, _Ursus_, Вы писали:

_U_>Я тут подумал...

_U_>какой класс лучше всего использовать для UNICODE строк:
_U_>- std::wstring
_U_>- ATL::CString
_U_>- _bstr_t
_U_>- что-то самописное ?

_U_>Если основные требования — скорость и UNICODE.

_U_>Чем пользуетесь вы? Только аргументированно, плиз.
Кстати, для работы с юникодом офигенно удобно использовать QString из qt. Из недостатков — довольно "толстый" класс, но зато, всё что нужно уже есть. Плюс в библиотеки есть набор кодеков, позволяющий конвертировать в юникод и обратно из здорового набора разных кодировок.
"To protect people you must slay people. To let people live you must let people die. This is the true teaching of the sword."
-Seijuro Hiko, "Rurouni Kensin"
Re[3]: std::wstring vs. ATL::CString vs. _bstr_t ?
От: Roman Odaisky Украина  
Дата: 14.06.08 11:59
Оценка:
Здравствуйте, shrecher, Вы писали:

S>Я не уверен, что в std::string можно хранить utf-8. Поведение методов типа length и всех от него зависимых не будет учитывыть UTF-8 кодировку и будет возвращать неверные значения.


В 150-й раз.

Зачем тебе вообще нужен std::string::size()?! Для чего ты собираешься использовать это число? Зачем тебе знать, из скольки Unicode code points состоит твоя строка?!
До последнего не верил в пирамиду Лебедева.
Re[2]: std::wstring vs. ATL::CString vs. _bstr_t ?
От: _Ursus_  
Дата: 14.06.08 13:26
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>Скорость чего конкретно?


Скорее, имеется ввиду overall performance, ну, вы понимаете
Т.е., вот есть у меня проект, доставшийся в наследство от другой команды, и в нем дикая мешанина из std::string, std::wstring, CString и _bstr_t.
Это жутко нервирует, и хочется все привести к единообразию — чтобы класс для строк был ОДИН.
Re[4]: std::wstring vs. ATL::CString vs. _bstr_t ?
От: shrecher  
Дата: 14.06.08 15:05
Оценка:
Здравствуйте, c-smile, Вы писали:

S>>Я не уверен, что в std::string можно хранить utf-8. Поведение методов типа length и всех от него зависимых не будет учитывыть UTF-8 кодировку и будет возвращать неверные значения.


CS>неверные значения чего?


неверные значения длинны стоки. Она будет возвращена в байтах, а не символах. К примеру


std::string s;
s = "some uft8 text";

for( int pos=0; pos < s.length(); pos ++ )
{
   printf( "%c", s[pos] ); // ошибка !!!
}




все производные методы тоже страдают темже недостатком
s.substr() // тоже не учитывает uft8 символы.

в тоже время, для std::wstring все будет работать ок в utf-16.
Re[4]: std::wstring vs. ATL::CString vs. _bstr_t ?
От: shrecher  
Дата: 14.06.08 15:08
Оценка:
Здравствуйте, Roman Odaisky, Вы писали:

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


S>>Я не уверен, что в std::string можно хранить utf-8. Поведение методов типа length и всех от него зависимых не будет учитывыть UTF-8 кодировку и будет возвращать неверные значения.


RO>В 150-й раз.


RO>Зачем тебе вообще нужен std::string::size()?! Для чего ты собираешься использовать это число? Зачем тебе знать, из скольки Unicode code points состоит твоя строка?!


Где ты видищь size? Я про length писал. Зачем нужно знать сколько длинна строки в символах? Дык это давольно частая операция. К примеру если распарсить что-то надо.
Re[4]: std::wstring vs. ATL::CString vs. _bstr_t ?
От: shrecher  
Дата: 14.06.08 15:11
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>Также важен набор операций со строками. Просто хранение текста — это одно. Манипуляции — это другое.


Ну для хранения можно и просто вектор использовать. Обычно от класса-строка требуется несколько больше чем тупое хранение.
Re[3]: std::wstring vs. ATL::CString vs. _bstr_t ?
От: Kluev  
Дата: 14.06.08 19:25
Оценка:
Здравствуйте, _Ursus_, Вы писали:

_U_>Здравствуйте, c-smile, Вы писали:


CS>>Скорость чего конкретно?


_U_>Скорее, имеется ввиду overall performance, ну, вы понимаете

_U_>Т.е., вот есть у меня проект, доставшийся в наследство от другой команды, и в нем дикая мешанина из std::string, std::wstring, CString и _bstr_t.
_U_>Это жутко нервирует, и хочется все привести к единообразию — чтобы класс для строк был ОДИН.

напиши свой собственный велосипед и в нем сделай все, что тебе нужно.
Re[5]: std::wstring vs. ATL::CString vs. _bstr_t ?
От: Roman Odaisky Украина  
Дата: 14.06.08 20:39
Оценка: +1
Здравствуйте, shrecher, Вы писали:

S>>>Я не уверен, что в std::string можно хранить utf-8. Поведение методов типа length и всех от него зависимых не будет учитывыть UTF-8 кодировку и будет возвращать неверные значения.


RO>>В 150-й раз.

RO>>Зачем тебе вообще нужен std::string::size()?! Для чего ты собираешься использовать это число? Зачем тебе знать, из скольки Unicode code points состоит твоя строка?!

S>Где ты видищь size? Я про length писал. Зачем нужно знать сколько длинна строки в символах? Дык это давольно частая операция. К примеру если распарсить что-то надо.


std::string::size() и std::string::length() — это одно и то же. Лучше использовать size(), потому что он так называется и в других контейнерах.

Так вот, приведи, пожалуйста, хоть один пример, где нужен std::string::size() (или length()).

(Кстати, если речь о парсинге чего-нибудь, то кодировка тебя интересует в последнюю очередь. Если ты хочешь разделить, к примеру, путь на компоненты, то слеш выглядит одинаково что в ASCII, что в UTF-8, а то, что между слешами, — просто последовательность байт.)
До последнего не верил в пирамиду Лебедева.
Re[5]: std::wstring vs. ATL::CString vs. _bstr_t ?
От: c-smile Канада http://terrainformatica.com
Дата: 14.06.08 20:47
Оценка:
Здравствуйте, shrecher, Вы писали:

S>>>Я не уверен, что в std::string можно хранить utf-8. Поведение методов типа length и всех от него зависимых не будет учитывыть UTF-8 кодировку и будет возвращать неверные значения.


CS>>неверные значения чего?


S>неверные значения длинны стоки. Она будет возвращена в байтах, а не символах. К примеру

S>в тоже время, для std::wstring все будет работать ок в utf-16.

std::wstring::length() возвращает количесво utf-16 code units.
А std::wstring::length() возвращает количесво utf-8 code units.

Какая разница?
Re[5]: Опять это заблуждение
От: Roman Odaisky Украина  
Дата: 14.06.08 20:48
Оценка:
Здравствуйте, shrecher, Вы писали:

CS>>неверные значения чего?

S>неверные значения длинны стоки. Она будет возвращена в байтах, а не символах. К примеру

S>

S>std::string s;
S>s = "some uft8 text";

S>for( int pos=0; pos < s.length(); pos ++ )
S>{
S>   printf( "%c", s[pos] ); // ошибка !!!
S>}
S>


Вот твой же код, дополненный до компилируемого состояния. Запусти.
#include <string>
#include <iostream>
#include <cstdio>

int main()
{
    std::string const s = "Что за распространенное заблуждение. Прямо déjà vu.";

    for( int pos=0; pos < s.length(); pos ++ )
    {
       std::printf( "%c", s[pos] ); // какая ошибка?!
    }
}

...и он выведет строку в точности.

S>все производные методы тоже страдают темже недостатком

S>s.substr() // тоже не учитывает uft8 символы.

Снова 25.
std::string const s = "мама мыла раму";
std::cout << s.substr(s.find("ы")) << std::endl;


S>в тоже время, для std::wstring все будет работать ок в utf-16.


Не будет! UTF-16 с тем же успехом содержит символы, которые занимают больше двух байт. Только они встречаются реже, что создает видимость отсутствия проблемы, но никак не решает ее.
До последнего не верил в пирамиду Лебедева.
Re[6]: Опять это заблуждение
От: shrecher  
Дата: 15.06.08 01:50
Оценка:
Здравствуйте, Roman Odaisky, Вы писали:


RO>...и он выведет строку в точности.


Фиг тебе. У тебя строка на русском и совпадает кодировка, попробуй вставить китайский иероглиф, получишь warning C4566.

Все проблема в том, внутри std::string использует strlen, которая не заботится о uft8 представлении. Поэтому когда один символ занимает 2 байта strlen вернет 2, не один.

Вот кусок кода считывающий из файла uft8. Файлы содеражат 4 китайских иероглифа. Первый пример некорректно печатает длинну как 15 символов, а другой работает в uft16 и печатает 4 (корректно)

utf8
http://files.rsdn.ru/69223/text.txt

utf-16 (unicode)
http://files.rsdn.ru/69223/textu.txt

int main()
{ 
    char buffer[256];
    memset( buffer, 0, sizeof(buffer) );
    {
        FILE *src = fopen( "text.txt", "rb"); //utf-8 
        if( !src )
            return 0;

        fseek( src, 0, SEEK_END);
        int size=ftell(src);
        if( size>sizeof(buffer) )
            return -1;
        fseek( src, 0, SEEK_SET);
        fread( buffer, 1, size, src); 
        fclose(src);
        buffer[size] = 0;

        std::string const s = buffer;
        printf( "std::string len=%d\n", s.length() ); // print 15
    }



    memset( buffer, 0, sizeof(buffer) );
    {
        FILE *src = fopen( "textu.txt", "rb"); // utf 16
        if( !src )
                return 0;

        fseek( src, 0, SEEK_END);
        int size=ftell(src)-2;
        if( size>sizeof(buffer) )
            return -1;
        fseek( src, 2, SEEK_SET); // skip unicode prefix
        fread( buffer, 1, size, src); 
        fclose(src);

        std::wstring const ws = (wchar_t *)buffer;
        printf( "utf16 len=%d\n", ws.length() );  // print 4
    }
}



S>>в тоже время, для std::wstring все будет работать ок в utf-16.


RO>Не будет! UTF-16 с тем же успехом содержит символы, которые занимают больше двух байт. Только они встречаются реже, что создает видимость отсутствия проблемы, но никак не решает ее.


Ух загнул!
Re[6]: std::wstring vs. ATL::CString vs. _bstr_t ?
От: shrecher  
Дата: 15.06.08 01:59
Оценка: -2
Здравствуйте, Roman Odaisky, Вы писали:

RO>Так вот, приведи, пожалуйста, хоть один пример, где нужен std::string::size() (или length()).


твой пример вполне подходит
RO>Если ты хочешь разделить, к примеру, путь на компоненты, то слеш выглядит одинаково что в ASCII, что в UTF-8, а то, что между слешами, — просто последовательность байт.)

Здесь проблема не в англ. "\", в том, что какой-нибудь китайский иероглиф кодируется как 2 два символа, где один совпадет с кодом слэша. К примеру \5. В этом случае, стока пути будет выглядеть как "c:\....\5...\", здесь второй слэш это часть символа, а не разделитель пути. Поэтому если ты используешь str::string и его метод "s.find( "\\" );", то результат будет неверный, т.к std::string не заботится о кодировке, а просто рассматривает строку как набор символов.
Re[7]: std::wstring vs. ATL::CString vs. _bstr_t ?
От: Cyberax Марс  
Дата: 15.06.08 02:16
Оценка: 1 (1) +5
Здравствуйте, shrecher, Вы писали:

S> Здесь проблема не в англ. "\", в том, что какой-нибудь китайский иероглиф кодируется как 2 два символа, где один совпадет с кодом слэша.

Это невозможно.

Может стоит-таки прочитать про UTF-8, а не придумывать фигню?
Sapienti sat!
Re[7]: Опять это заблуждение
От: Cyberax Марс  
Дата: 15.06.08 02:26
Оценка:
Здравствуйте, shrecher, Вы писали:

S>Вот кусок кода считывающий из файла uft8. Файлы содеражат 4 китайских иероглифа. Первый пример некорректно печатает длинну как 15 символов, а другой работает в uft16 и печатает 4 (корректно)

А сколько символов вот в этой строке: "Lux æterna finale"?

И я это ещё не вспоминаю про языки со сложным написанием символов: http://en.wikipedia.org/wiki/Complex_Text_Layout
Sapienti sat!
Re[3]: std::wstring vs. ATL::CString vs. _bstr_t ?
От: bnk СССР http://unmanagedvisio.com/
Дата: 15.06.08 07:37
Оценка: 1 (1)
Здравствуйте, _Ursus_, Вы писали:

_U_>Скорее, имеется ввиду overall performance, ну, вы понимаете

_U_>Т.е., вот есть у меня проект, доставшийся в наследство от другой команды, и в нем дикая мешанина из std::string, std::wstring, CString и _bstr_t.

_U_>Это жутко нервирует, и хочется все привести к единообразию — чтобы класс для строк был ОДИН.


Рекомендую оставить все как есть.
Скорее всего, на это мешанину есть причины, программисты ведь обычно не делают абстракное зло.

Например:
— std::wstring -> работа с какой-нибудь библиотекой (из boost?), которая ничего кроме std::wstring не хочет
— CString -> анологично, MFC/ATL/WTL
— bstr_t -> работа с COM через директиву #import, тоже без вариантов.

То есть, класс строк который вы используете, определяется в основном тем, какие библиотеки вы используете.
Re[7]: Опять это заблуждение
От: Roman Odaisky Украина  
Дата: 15.06.08 08:15
Оценка:
Здравствуйте, shrecher, Вы писали:

RO>>...и он выведет строку в точности.


S>Фиг тебе. У тебя строка на русском и совпадает кодировка, попробуй вставить китайский иероглиф, получишь warning C4566.


С чего бы это? Тем более, что я выше по течению приводил другой фрагмент кода, в котором в строке были как русские буквы, так и французские (с диакритическими знаками).


S>Все проблема в том, внутри std::string использует strlen, которая не заботится о uft8 представлении. Поэтому когда один символ занимает 2 байта strlen вернет 2, не один.


S>Вот кусок кода считывающий из файла uft8. Файлы содеражат 4 китайских иероглифа. Первый пример некорректно печатает длинну как 15 символов, а другой работает в uft16 и печатает 4 (корректно)


Ну и что?!

В третий раз спрашиваю: зачем тебе знать размер строки в Unicode code points?!

Кстати, проведи эксперимент. Положи в свой текстовый файл, к примеру, скрипичный ключ (U+1D11E) и запусти свою программу. Сколько символов она насчитает?

P. S. UTF, не «UFT»: Unicode Transformation Format.
До последнего не верил в пирамиду Лебедева.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.