Страница 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 буква "Ё" кодируется четырьмя! байтами.
Так вот почему проект "Ё-мобиль" у Михаила Прохорова не состоялся - не ту кодировку использовали. :-)

А вообще-то данная тема уже когда-то поднималась на форуме.
Вот ссылка на неё.