Страница 3 из 4
Re: Не получается приведение
Добавлено: 10 апр 2014, 12:03
Сионист
WinMain писал(а):И ты считаешь это удачным решением задачи? Если строку в виде std::string наращивать посимвольно, то это приведёт к жудким тормозам при выполнении программы. На коротких строках это может и незаметно будет, но на более длинных текстах программа будет просто умирать.
А как же тогда защититься от нулевых байтов в UTF-8? Ведь первый из них будет принят за терминальный. Или в этом коде запрещены нулевые байты?
Re: Не получается приведение
Добавлено: 10 апр 2014, 12:05
Сионист
Romeo писал(а):Не работает с кириллицей. Вместо русских букв будут вставлены усечённые до одного байта ASCII символы с неожиданным значением.
Нифига подобного. Работает и с вязью, и с кириллицей и ничего не усекается, что показывают и тесты, и элементарнейший анализ.
Re: Не получается приведение
Добавлено: 10 апр 2014, 12:23
Romeo
Нифига подобного. Работает и с вязью, и с кириллицей и ничего не усекается, что показывают и тесты, и элементарнейший анализ.
Кириллица, плохой пример. Но можно подобрать символы, которые будет с нулевым байтом.
А как же тогда защититься от нулевых байтов в UTF-8? Ведь первый из них будет принят за терминальный. Или в этом коде запрещены нулевые байты?
Если ты защитишься от нулевых байтов путём их удаления (как у тебя сейчас сделано), то ты исковеркаешь текст. Нулевые байты нужно оставлять, они тоже несут смысловую нагрузку в UTF.
Re: Не получается приведение
Добавлено: 10 апр 2014, 12:46
WinMain
В кодировке UTF-8 нет нулевых байтов между символами (кроме последнего в конце строки).
В отличие от обычной UNICODE-строки, где каждый символ кодируется строго двумя байтами, в кодировке UTF-8 символы латиницы (с кодом до 127) кодируются одним байтом, а символы других алфавитов - двумя или четырьмя байтами. И ни один из этих байтов не должен быть нулевым. К сведению: в кодировке UTF-8 буква "Ё" кодируется четырьмя! байтами.
Re: Не получается приведение
Добавлено: 10 апр 2014, 12:52
Сионист
Romeo писал(а):Если ты защитишься от нулевых байтов путём их удаления (как у тебя сейчас сделано), то ты исковеркаешь текст. Нулевые байты нужно оставлять, они тоже несут смысловую нагрузку в UTF.
У меня совсем не так сделано, я как раз копирую
каждый байт.
Re: Не получается приведение
Добавлено: 10 апр 2014, 12:54
Сионист
WinMain писал(а):В отличие от обычной UNICODE-строки, где каждый символ кодируется строго двумя байтами, в кодировке UTF-8 символы латиницы (с кодом до 127) кодируются одним байтом, а символы других алфавитов - двумя или четырьмя байтами.
При этом первый байт префиксный и заведомо ноля не содержит, так как признак следующего байта - первый больше 127. А второй может быть нулевым? Или третий? Или четвёртый?
Re: Не получается приведение
Добавлено: 10 апр 2014, 12:56
Romeo
WinMain писал(а):В кодировке UTF-8 нет нулевых байтов между символами (кроме последнего в конце строки).
В отличие от обычной UNICODE-строки, где каждый символ кодируется строго двумя байтами, в кодировке UTF-8 символы латиницы (с кодом до 127) кодируются одним байтом, а символы других алфавитов - двумя или четырьмя байтами. И ни один из этих байтов не должен быть нулевым. К сведению: в кодировке UTF-8 буква "Ё" кодируется четырьмя! байтами.
Похоже мои интуитивные знания UTF-8 спутались со стандартом UTF-16. Если внутренних нулей не бывает, то и подход с вектором символов, ровно как и побайтное копирование, не нужны.
Сионист писал(а):При этом первый байт префиксный и заведомо ноля не содержит, так как признак следующего байта - первый больше 127. А второй может быть нулевым? Или третий? Или четвёртый?
Я только что внимательно изучил стандарт
UTF-8. Судя по всему третий и четрвёртый тоже не могут быть нулевыми.
Re: Не получается приведение
Добавлено: 10 апр 2014, 13:27
Сионист
Код: Выделить всё
int main()
{
std::string s="";
s+='\0';
s+='\0';
s+='\0';
s+='\0';
s+='\0';
s+='\0';
std::cout<<s.length()<<std::endl;
return 0;
}
вывело 6, а if под циклом не валяется, так что пропуском нулевых байт у меня не воняет.
Re: Не получается приведение
Добавлено: 10 апр 2014, 13:34
Сионист
Прочитал по ссылке, там у всех байтов префиксы, начинающиеся с единичного бита, так что нулевых быть ещё и не может.
Код: Выделить всё
std::string WStringToUtf8 (const
std::wstring &s )
{
char *Buffer;
size_t BufferSize;
std::string Result="";
if (!s.empty())
{
BufferSize=WideCharToMultiByte(CP_UTF8, 0, s.c_str(), s.length(), NULL, 0, NULL, NULL);
Buffer=new char[BufferSize]+1;
if (Buffer!=NULL)
{
WideCharToMultiByte(CP_UTF8, 0, s.c_str(), s.length(), Buffer, BufferSize, NULL, NULL);
Buffer[BufferSize]=0;
Result=Buffer;
delete [] Buffer;
}
}
return Result;
}
Re: Не получается приведение
Добавлено: 10 апр 2014, 13:54
Decoder
К сведению: в кодировке UTF-8 буква "Ё" кодируется четырьмя! байтами.
Так вот почему проект "Ё-мобиль" у Михаила Прохорова не состоялся - не ту кодировку использовали. :-)
А вообще-то данная тема уже когда-то поднималась на форуме.
Вот ссылка на неё.