Как присвоить переменной char значение в UTF8 кодировке?

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

Re: Как присвоить переменной char значение в UTF8 кодировке?

Сообщение Odyssey » 27.12.2009 20:34:35

Код: Выделить всё
writeln(UTF8ToConsole(Symbol));

Если так, то нужно:
Код: Выделить всё
writeln(UTF8ToConsole(AnsiToUTF8(Symbol)));

Чуть выше, для того чтобы всё-таки запихнуть русский символ в 1 байт, было предложено воспользоваться кодировкой windows-1251, UTF8ToAnsi как раз и преобразует строку из UTF-8 в windows-1251 (на русской Windows).
В windows-1251 кириллические символы занимают 1 байт и без проблем умещаются в char. Но поскольку у функции UTF8ToConsole на входе должна быть строка в utf-8, то придётся сконвертировать windows-1251 обратно в utf-8, а уже затем в кодировку системной консоли (UTF8ToConsole).

Александр Яшин писал(а):Здесь я как раз и имел в виду, что "Если в бочонке было меньше литра (читай "< 128") -- наше счастье"

Это для латиницы. А для кириллицы в бочонке уже два литра, и в литровую банку их не залить. Единственный вариант -- преобразовать воду во что-то другое (UTF8ToAnsi).
Odyssey
энтузиаст
 
Сообщения: 580
Зарегистрирован: 29.11.2007 17:32:24

Re: Как присвоить переменной char значение в UTF8 кодировке?

Сообщение Александр Яшин » 28.12.2009 17:49:06

Не хотелось бы открывать новую тему, может кто-нибудь здесь ответит. В принципе вопрос близко к теме.
Короче говоря, при вводе строки с клавиатуры, насколько я понимаю, происходит автоматическое преобразование в нужный тип. Если объявлена переменная типа string, то входная строка с клавиатуры в кодировке СР866 будет преобразована в строку в кодировке UTF8. Если да, то почему не работает следующий код:
Код: Выделить всё
program project1;
uses
  FileUtil, SysUtils, CRT, LCLProc;
var
  str, s: string;
begin
  s:= 'абвг';
  writeln(UTF8ToConsole('Введите строку'));
  readln(str);
  if comparestr(s, str) = 0 then
    writeln(UTF8ToConsole('Строки совпали'))
  else
    writeln(UTF8ToConsole('Строки не совпадают'));
  readkey;
end. 


Как бы я не преобразовывал входную строку str (UTF8ToAnsi, AnsiToUTF8) строки не совпадают.
Только если преобразовать строку s функцией (UTF8ToConsole(s)) строки совпадают. Значит исходное предположение, что строка с клавиатуры автоматически преобразуется в нужный тип неверно? Тогда как преобразовать СР866 в UTF8?
Функцию, обратную UTF8ToConsole я не нашел
Александр Яшин
новенький
 
Сообщения: 67
Зарегистрирован: 21.11.2009 09:31:01

Re: Как присвоить переменной char значение в UTF8 кодировке?

Сообщение Alexx2000 » 28.12.2009 18:20:32

Александр Яшин писал(а):Тогда как преобразовать СР866 в UTF8?
Функцию, обратную UTF8ToConsole я не наше

Например так:
Код: Выделить всё
function ConsoleToUTF8(const Str: AnsiString): UTF8String;
{$ifdef MSWindows}
var
  Dst: PChar;
{$endif}
begin
  Result:= Str;
  {$ifdef MSWindows}
  Dst:= AllocMem((Length(Result) + 1) * SizeOf(Char));
  if OEMToChar(PChar(Result), Dst) then
    Result:= SysToUTF8(Dst);
  FreeMem(Dst);
  {$endif}
end;
Аватара пользователя
Alexx2000
постоялец
 
Сообщения: 489
Зарегистрирован: 25.10.2006 00:22:07
Откуда: Мытищи

Re: Как присвоить переменной char значение в UTF8 кодировке?

Сообщение Александр Яшин » 28.12.2009 18:44:28

Пишет - Error: Identifier not found "OEMToChar"
Александр Яшин
новенький
 
Сообщения: 67
Зарегистрирован: 21.11.2009 09:31:01

Re: Как присвоить переменной char значение в UTF8 кодировке?

Сообщение Alexx2000 » 28.12.2009 18:59:12

Это WinAPI функция, соответственно нужно добавить в uses модуль Windows, его также можно заключить в $ifdef
Аватара пользователя
Alexx2000
постоялец
 
Сообщения: 489
Зарегистрирован: 25.10.2006 00:22:07
Откуда: Мытищи

Re: Как присвоить переменной char значение в UTF8 кодировке?

Сообщение Александр Яшин » 28.12.2009 19:07:16

Спасибо! Получилось.
Александр Яшин
новенький
 
Сообщения: 67
Зарегистрирован: 21.11.2009 09:31:01

Re: Как присвоить переменной char значение в UTF8 кодировке?

Сообщение Odyssey » 28.12.2009 20:46:46

Ещё как вариант можно воспользоваться функцией CP866ToUTF8() из модуля LConvEncoding.
Но то, что ConsoleToUTF8 в LCL нет -- это недостаток. Может быть стоит зарепортить в багтрекер и предложить реализацию Alexx2000?
Odyssey
энтузиаст
 
Сообщения: 580
Зарегистрирован: 29.11.2007 17:32:24

Re: Как присвоить переменной char значение в UTF8 кодировке?

Сообщение Alexx2000 » 28.12.2009 20:56:45

Меня тоже удивило наличие UTF8ToConsole и отсутствие ConsoleToUTF8, поэтому по аналогии для себя сделал эту функцию.
Аватара пользователя
Alexx2000
постоялец
 
Сообщения: 489
Зарегистрирован: 25.10.2006 00:22:07
Откуда: Мытищи

Re: Как присвоить переменной char значение в UTF8 кодировке?

Сообщение Max Rusov » 29.12.2009 02:15:17

Для общего развития хочу понять - зачем весь этот геморрой с UTF8? Почему не использовать WideChar/WideString - ведь это гораздо проще?
Max Rusov
постоялец
 
Сообщения: 191
Зарегистрирован: 25.04.2009 15:46:03

Re: Как присвоить переменной char значение в UTF8 кодировке?

Сообщение Odyssey » 29.12.2009 09:04:11

Наверное, это -- на вкус и цвет. Мне WideString не нравится, потому что не все символы входят в Basic Multilingual Plane, т.е. помещаются в два байта. Поэтому даже с WideString, если по-хорошему, нужно юзать UTF-16 с переменной длинной символа, но тогда вся фишка WideString пропадает. Да, я знаю, что реально символы за пределами BMP используются довольно редко, а страны, для которых это критично, например Китай, сами стараются по возможности отказаться от их использования. Но тем не менее, я считаю, что использовать Юникод, который не "юни", т.е. который не в состоянии представить всех символов, используемых в существующих языках -- это создавать локализаторам проблемы на ровном месте. А для проектов, для которых локализация вообще никак не планируется, можно с тем же успехом использовать windows-1251, это же ещё проще, чем WideString :)

Ещё один плюс UTF-8 -- совместимость, например, не нужно переписывать давно написанные парсеры, в которых все управляющие символы попадают в ASCII.
Odyssey
энтузиаст
 
Сообщения: 580
Зарегистрирован: 29.11.2007 17:32:24

Re: Как присвоить переменной char значение в UTF8 кодировке?

Сообщение Max Rusov » 29.12.2009 11:58:04

Вот как раз с точки зрения совместимости - WideString гораздо предпочтительней. В большинстве случаев все правки ограничиваются заменой типа (а в Delphi 2009+ даже этого не требуется :) ). А при работе с UTF8 нужно радикально менять алгоритмы. Плюс - это постоянное преобразование туда-сюда...
Max Rusov
постоялец
 
Сообщения: 191
Зарегистрирован: 25.04.2009 15:46:03

Re: Как присвоить переменной char значение в UTF8 кодировке?

Сообщение Александр Яшин » 29.12.2009 12:48:22

Если использовать WideChar, то при попытке присвоить значение все-равно выдает Error: Incompatible types: got "Constant String" expected "WideChar"
Поэтому я однозначно выбираю TUTF8Char.
При использовании WideString выдается ошибка на операторе readln(str) - Fatal: Unknown compilerproc "fpc_read_text_widestr". Check if you use the correct run time library.

И еще. После ввода строки с клавиатуры (при использовании обычных string) функции, например, Length(), Pos(), Copy() работают, хотя как выяснилось в этом топике, строка остается в кодировке СР866.
Значит вышеуказанные функции сначала преобразовывают строку в UTF8? Или эти функции годятся и для СР866?
Александр Яшин
новенький
 
Сообщения: 67
Зарегистрирован: 21.11.2009 09:31:01

Re: Как присвоить переменной char значение в UTF8 кодировке?

Сообщение Alexx2000 » 29.12.2009 16:07:30

Александр Яшин писал(а):Значит вышеуказанные функции сначала преобразовывают строку в UTF8?

Нет, данные функции предназначены для работы со строками в однобайтовой кодировке. Для UTF8 есть функции UTF8Length, UTF8Pos, UTF8Copy и .т.д.
Александр Яшин писал(а):Или эти функции годятся и для СР866?

В общем то да, например Length и Copy будут правильно работать, а вот с Pos надо учитывать, что искомая строка также должна быть в кодировке cp866.
Аватара пользователя
Alexx2000
постоялец
 
Сообщения: 489
Зарегистрирован: 25.10.2006 00:22:07
Откуда: Мытищи

Re: Как присвоить переменной char значение в UTF8 кодировке?

Сообщение Александр Яшин » 29.12.2009 18:30:44

Интересно, какая функция эффективней CP866ToUTF8() или ConsoleToUTF8()?
Твоя функция написана изящней (кстати, ты сам ее написал?), а вот насчет эффективности?!
Александр Яшин
новенький
 
Сообщения: 67
Зарегистрирован: 21.11.2009 09:31:01

Re: Как присвоить переменной char значение в UTF8 кодировке?

Сообщение Alexx2000 » 29.12.2009 19:09:27

Александр Яшин писал(а):Интересно, какая функция эффективней CP866ToUTF8() или ConsoleToUTF8()?

Скажем так, это две разные функции. CP866ToUTF8() будет корректной только для русской Windows (cp866 - кодировка для русского языка под DOS), а под другой Windows, используется соответственно другая кодировка в консоли. А ConsoleToUTF8() должна работать с любой кодировкой, используемой в консоли.
Александр Яшин писал(а):Твоя функция написана изящней (кстати, ты сам ее написал?), а вот насчет эффективности?!

Написал, это слишком громко сказано, просто обратил алгоритм функции UTF8ToConsole.
Аватара пользователя
Alexx2000
постоялец
 
Сообщения: 489
Зарегистрирован: 25.10.2006 00:22:07
Откуда: Мытищи

Пред.

Вернуться в Free Pascal Compiler

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 3

Рейтинг@Mail.ru