Обалденный глюк при работе со строками

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

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

Аватара пользователя
Stertor
новенький
Сообщения: 20
Зарегистрирован: 10.08.2014 18:11:12
Контактная информация:

Обалденный глюк при работе со строками

Сообщение Stertor »

Глюк сводится к тому, что нельзя получить 1 символ строки, если строка состоит из 1 символа.

Код: Выделить всё

procedure TForm1.Button1Click(Sender: TObject);
//Delphi
var
  str:string;
begin
   str:='ы';
     showmessage(str[1]); // ы
end;


Код: Выделить всё

procedure TForm1.Button1Click(Sender: TObject);
//FPC
var
  str:string;
begin
   str:='ы';
     showmessage(str[1]); // emptystr  :(  Ок, поправим...
     showmessage(pchar(str)[0]); // emptystr {facepalm}
end;


Версия FPC: 2.6.4
MiniQ
новенький
Сообщения: 81
Зарегистрирован: 28.01.2013 16:31:55

Сообщение MiniQ »

Что showmessage принимает на входе? string?
а ты ему даешь char
сделай так
showmessage(copy(str,1,1));
Аватара пользователя
Vapaamies
постоялец
Сообщения: 292
Зарегистрирован: 24.07.2012 22:37:59
Откуда: Санкт-Петербург
Контактная информация:

Сообщение Vapaamies »

Если строка в UTF-8, буква "ы" кодируется двумя байтами.
zub
долгожитель
Сообщения: 2890
Зарегистрирован: 14.11.2005 22:51:26
Контактная информация:

Сообщение zub »

>>Обалденный глюк при работе со строками
котегорично))
для полного понимания предлагаю еще поэкспериментироваь:

Код: Выделить всё

begin
   str:='s';
     showmessage(inttostr(length(str)));
     showmessage(str[1]);
end;

дальше какнибудб так:

Код: Выделить всё

begin
   str:='ы';
     showmessage(inttostr(length(str)));
     showmessage(inttostr(ord(str[1])));
     showmessage(inttostr(ord(str[2])));
end;

затем глянуть как в utf8 кодируются русские буквы и прогуглить кучу тем уже посвещенных этому вопросу... там и решение найдется:

Код: Выделить всё

uses lazutf8;
begin
   str:='ы';
     showmessage(inttostr(UTF8Length(str)));
     showmessage(UTF8copy(str,1,1));
end;
Аватара пользователя
Stertor
новенький
Сообщения: 20
Зарегистрирован: 10.08.2014 18:11:12
Контактная информация:

Сообщение Stertor »

Возможно, Вам покажется странным, господа, но приведенный мной пример нормально работает на юникодной дельфе 2009.

begin
str:='s';
showmessage(inttostr(length(str)));
showmessage(str[1]);
end;

Уже видел. Глюк возникает с русскими буквами, причем независимо от типа строки - будь это utf8string или unicodestring.

uses lazutf8;
begin
str:='ы';
showmessage(inttostr(UTF8Length(str)));
showmessage(UTF8copy(str,1,1));
end;


Мне нужно работать со строкой, как с массивом. Получается, что никак не обойтись без copy/midstr?
zub
долгожитель
Сообщения: 2890
Зарегистрирован: 14.11.2005 22:51:26
Контактная информация:

Сообщение zub »

>>Возможно, Вам покажется странным, господа, но приведенный мной пример нормально работает на юникодной дельфе 2009.

>>Уже видел. Глюк возникает с русскими буквами, причем независимо от типа строки - будь это utf8string или unicodestring.
>>Мне нужно работать со строкой, как с массивом. Получается, что никак не обойтись без copy/midstr?
1. Это не глюк
2. Ни что вам не мешает продолжать работать со строкой как с массивом. Просто учитывайте что символ может занимать не только 1 байт
Аватара пользователя
Stertor
новенький
Сообщения: 20
Зарегистрирован: 10.08.2014 18:11:12
Контактная информация:

Сообщение Stertor »

1. Это не глюк

Буду спорить. Отчего же тогда в Delphi работает?

zub писал(а):Просто учитывайте что символ может занимать не только 1 байт

Просвети?

Код: Выделить всё

procedure TForm1.Button1Click(Sender: TObject);
var
  str:string;
  s:string;
  i:integer;
begin
   str:='Не называйте это паскалем. Это бейсик какой-то.';
   for i:=1 to utf8length(str) do // а нафига тогда, спрашивается, length??
   begin
      s:=utf8copy(str,i,1); // а Copy тогда зачем???
    showmessage(s);
   end;
end;
zub
долгожитель
Сообщения: 2890
Зарегистрирован: 14.11.2005 22:51:26
Контактная информация:

Сообщение zub »

>>Буду спорить. Отчего же тогда в Delphi работает?
вместо споров лучше таки глянь что из себя представляет кодировка utf8
кстати,
>>причем независимо от типа строки - будь это utf8string или unicodestring.
лишний раз подтверждает что глюки в программе а не в компиляторе, вы забыли перекодировать строку перед тем как закинуть ее в unicodestring.
В последних дельфях внутренняя кодировка строк utf16 емнип, в fpc 2.6 ее как таковой нет, нужно самому учитывать и перекодировать строки туда-сюда.
Могу посоветовать подождать годик другой fpc2.8 и LCL совместимую с ним - там будет также как в delphi. Уже сейчас можно потыкать 2.7.1 но будут еще более обалденные "глюки", т.к. LCL пока не умеет новые строки

>>Просвети?
На тему? в 2.6 строка - массив байтов, работай как с массивом)) - не, нехочу - "глюки"))
Аватара пользователя
Vapaamies
постоялец
Сообщения: 292
Зарегистрирован: 24.07.2012 22:37:59
Откуда: Санкт-Петербург
Контактная информация:

Сообщение Vapaamies »

Stertor писал(а):Возможно, Вам покажется странным, господа, но приведенный мной пример нормально работает на юникодной дельфе 2009.

Потому что в Delphi всё реализовано по уму, а в FPC на "отвяжись".
zub
долгожитель
Сообщения: 2890
Зарегистрирован: 14.11.2005 22:51:26
Контактная информация:

Сообщение zub »

>>Потому что в Delphi всё реализовано по уму, а в FPC на "отвяжись".
Официального стабильного FPC с внутренней перекодировкой строк пока нет, такчто оставим такие заявления до выхода 2.8
На самом деле проблемы вида

Код: Выделить всё

showmessage(str[1]); // emptystr  :(  Ок, поправим...

только с виду такие страшные. в свое время перевел свой быдлокодный парсер с ansi на utf8 абсолютно безболезненно, думаю перевод на utf16 будет гораздо более проблемным.
часто из строки нужно выдрать один символ? гораздо чаще нужно выдрать подстроку, а она что в анси что в utf8 или utf16 последовательность байт\слов. Но даже если приспичело выдирать посимвольно - делать ставку на то что символ=байт\слово - ошибочно
Аватара пользователя
hinst
энтузиаст
Сообщения: 781
Зарегистрирован: 12.04.2008 18:32:38

Сообщение hinst »

кароч в лазарусе UTF-8, а в Delphi WideChar, поэтому s[1] не буит работать как хочет начавший тему

Добавлено спустя 3 минуты 25 секунд:
и если начавший тему не может справиться с такой примитивной задачей как разобраться-въехать что нужно сделать чтобы работало как он хотел, то хм что ж........

Добавлено спустя 52 секунды:
твоя работа - твой головняк думать как это реализовать
Аватара пользователя
Максим
энтузиаст
Сообщения: 599
Зарегистрирован: 27.07.2007 01:51:43
Откуда: Москва

Сообщение Максим »

Stertor писал(а):Возможно, Вам покажется странным, господа, но приведенный мной пример нормально работает на юникодной дельфе 2009.

Приведённый в стартовом посте код в общем случае в Delphi также неработоспособен. В UTF-16, внезапно, помимо двухбайтных символов есть и четырёхбайтные.

Vapaamies писал(а):Потому что в Delphi всё реализовано по уму, а в FPC на "отвяжись".

Нет, реализовано не на "отвяжись", а чтобы над вами персонально поиздеваться. :mrgreen:
sign
энтузиаст
Сообщения: 1131
Зарегистрирован: 30.08.2009 09:20:53

Сообщение sign »

Stertor писал(а):Глюк сводится к тому, что нельзя получить 1 символ строки, если строка состоит из 1 символа.

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

Код: Выделить всё

S := 'Привет';
Ch := S[3];

Ch - ни разу не будет 'и';
Vadim
долгожитель
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Сообщение Vadim »

Код: Выделить всё

procedure TForm1.Button1Click(Sender: TObject);
//Delphi
var
  str:string;
begin
   str:='ы';
     showmessage(UTF8Copy(str, 1, 1)); // ы
end;

и все дела... ;-)
Последний раз редактировалось Vadim 22.08.2014 04:56:45, всего редактировалось 1 раз.
SSerge
энтузиаст
Сообщения: 971
Зарегистрирован: 12.01.2012 05:34:14
Откуда: Барнаул

Сообщение SSerge »

Vadim, запятую забыл :D
Ответить