Строковый зоопарк

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

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

Строковый зоопарк

Сообщение and » 18.08.2011 21:53:04

Может, мне в "Обучение" надо, что-то я на старости лет совсем заблудился в строковых типах...

Сначала немного лирики.
Даже если отбросить экзотику-архаику типа pString, array[1..N]of char и забить на shortString, остаются три (якобы легко совместимых взаимно) ходовых строковых типа: string и pChar. Три - потому что pChar'ов ДВА: pChar, созданный через GetMem - не то же, что pChar, создаваемый StrAlloc'ом! И смешивать два подхода к распределению-освобождению памяти под pChar чревато AV'шкой: если память выделялась через StrAlloc, то освобождать нужно не FreeMem(p), а FreeMem(p-SizeOf(cardinal)) - а лучше, конечно, StrDispose(p). В обратную сторону (т.е. вызовом StrDispose отдать выделенное через GetMem), кажется, вообще никак.

А теперь конкретные вопросы.
1) Можно ли отличить один pChar от другого, кроме как методом тыка и try-except?
2) Нужно в строку pChar записать строку string. Ессно, p:=pChar(s) не подходит: содержимое p будет валидно только на время жизни s. (Если не ошибаюсь, такое присваивание не увеличит счётчик ссылок s. Или ошибаюсь?).
Ничего менее громоздкого, чем
Код: Выделить всё
if Assigned(p)
  then try
         StrDispose(p)
       except
         FreeMem(p)
{случаи, когда pChar получался присваиванием string'а или массива символов, для простоты проигнорирую}
       end;
p:=StrAlloc(Length(s)+1); {или +1 не надо?}
StrPCopy(p,s)
не придумывается. И подозреваю, что так быть не должно, иначе не могу объяснить, почему среди библиотечных функций нет аналога AssignStr, но для pChar.
Аватара пользователя
and
постоялец
 
Сообщения: 124
Зарегистрирован: 16.09.2009 17:11:01
Откуда: г. Гомель, Беларусь

Re: Строковый зоопарк

Сообщение Kitayets » 18.08.2011 23:05:57

pChar - по сути указатель, по этому абсолютно логично, что p:=pChar(s), будет валидно только до освобождения s, ведь тут p будет указывать на первый символ строки (сразу за служебной информацией) структуры которая реализует string. правильно на мой взгляд - выделить память равную длине (в байтах) s + 1 и скопировать туда содержимое строки + добавить в конец \0, т.е. как это делается в классическом "С", а всякие stralloc - это от лукавого.
Kitayets
постоялец
 
Сообщения: 171
Зарегистрирован: 05.05.2010 21:15:24

Re: Строковый зоопарк

Сообщение Max Rusov » 18.08.2011 23:21:47

Вам еще предстоит открыть разницу между AnsiString, WideString и UnicodeString...
Max Rusov
постоялец
 
Сообщения: 191
Зарегистрирован: 25.04.2009 15:46:03

Re: Строковый зоопарк

Сообщение Ism » 19.08.2011 00:50:40

Где AnsiString = String = UTF8String в unix :)

http://www.sql.ru/forum/actualutils.asp ... g=10465427
Ism
энтузиаст
 
Сообщения: 908
Зарегистрирован: 06.04.2007 17:36:08

Re: Строковый зоопарк

Сообщение and » 19.08.2011 02:11:44

Kitayets писал(а):pChar - по сути указатель, по этому абсолютно логично, что p:=pChar(s), будет валидно только до освобождения s
Полностью согласен. Поэтому и предостерёг сразу юные горячие головы, которые могли бы присоветовать такое "решение".
Kitayets писал(а):правильно на мой взгляд - выделить память равную длине (в байтах) s + 1 и скопировать туда содержимое строки + добавить в конец \0
Это хорошо бы (хотя такая работа со "строками" стала одной из причин моей нелюбви к "Сям"), но чисто технически в FPC являются корректным аж 4 (как минимум) разных pChar'а, которые я не могу отличить один от другого, и организационно заставить всех выбрать какую-то одну разновидность pChar'а я тоже не могу.

Max Rusov писал(а):Вам еще предстоит открыть разницу между AnsiString, WideString и UnicodeString...
Неее, это пройденный этап, с этим я ужЕ давно смирился :-) Как и с некорректностью обработки привычными Pos, Length etc строк UTF8, стандартных для Лазаруса. И красота Виртопаскального подхода к s[5] как пятому _символу_ строки тоже ужЕ оплакана и похоронена :-(

2Ism: Спасибо, интересно было почитать.
Аватара пользователя
and
постоялец
 
Сообщения: 124
Зарегистрирован: 16.09.2009 17:11:01
Откуда: г. Гомель, Беларусь

Re: Строковый зоопарк

Сообщение Vadim » 19.08.2011 06:25:46

and
Так Вы сами то и используйте какой-нибудь один подход к PChar, тогда и не будет никакой путаницы. ;) Вы же сами понимаете, что это проблема не языковая, а внутреннего предпочтения программиста.
Vadim
долгожитель
 
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Re: Строковый зоопарк

Сообщение vada » 19.08.2011 09:48:18

Я использую исключительно
Код: Выделить всё
S: String;

Но! Как and уже писал s[5] забыть как и не было, и четно говоря запаривает UTF8Encoder и UTF8DEcoder. Мозги закипают что из них в данный момент нужно использовать. Приходится решать через попробовать. Жутко неудобно.
А походив по детским граблям с PChar, постарался забыть про их существование.

Согласен, зоопарк со строками ЖУТКИЙ.
Аватара пользователя
vada
энтузиаст
 
Сообщения: 691
Зарегистрирован: 14.02.2006 13:43:17

Re: Строковый зоопарк

Сообщение Odyssey » 19.08.2011 12:30:02

and писал(а):1) Можно ли отличить один pChar от другого, кроме как методом тыка и try-except?

Имхо, гарантированно отличить -- нельзя, причём нельзя даже методом тыка и try-except. Мы не знаем адрес начала блока памяти, выделенного под строку, поэтому перед нашим указателем может быть длина нашего блока памяти, а может быть хвост предыдущего блока памяти, чужого, в котором может быть всё что угодно.
and писал(а):2) Нужно в строку pChar записать строку string. ...
Ничего менее громоздкого, чем ... не придумывается.

Я бы делал почти так же, через StrPCopy, только освобождать предыдущий PChar нужно тем же методом, которым он создавался(GetMem/FreeMem, SysUtils.StrAlloc/SysUtils.StrDispose, Strings.StrAlloc/Strings.StrDispose). На try except я бы не полагался, даже если такой подход и не попортит чужую память, не факт что он освободит нашу.
and писал(а):И подозреваю, что так быть не должно, иначе не могу объяснить, почему среди библиотечных функций нет аналога AssignStr, но для pChar.
Может быть потому, что способов освобождения PChar -- несколько, и такая функция не знала бы какой из них использовать?
Odyssey
энтузиаст
 
Сообщения: 580
Зарегистрирован: 29.11.2007 17:32:24

Re: Строковый зоопарк

Сообщение SII » 19.08.2011 14:43:55

Эх... Хорошо, что в Аде жёсткая стандартизация, не зависящая от разработчиков компилятора :)
Кстати, небольшой вопрос к знатокам: в FPC обращаться к конкретным символам по индексу в строках типа UnicodeString можно? В современных Дельфях, помнится, можно (нельзя к AnsiString, где индексироваться будут байты, а не символы).
SII
новенький
 
Сообщения: 64
Зарегистрирован: 24.06.2007 17:15:09
Откуда: Зеленоград

Re: Строковый зоопарк

Сообщение vada » 19.08.2011 14:58:25

Компилятор ругается.
Аватара пользователя
vada
энтузиаст
 
Сообщения: 691
Зарегистрирован: 14.02.2006 13:43:17

Re: Строковый зоопарк

Сообщение Odyssey » 19.08.2011 15:43:29

SII писал(а):в FPC обращаться к конкретным символам по индексу в строках типа UnicodeString можно?

Смотря что понимать под "символами". Если, например, вас устроит то, что в одной из нормальных форм Юникода
Й -- это два "символа" -- И и крышечка, то можно.

В Юникоде нет "символов" в привычном понимании (как в ASCII или cp1251) -- всегда атомарных, неделимых, имеющих один и тот же код. Поэтому проблема с доступом по индексу затрагивает не только FPC, но и все средства разработки, имеющие дело с Юникодом. Проблема отлично (хотя и грубовато) описана тут: http://live.julik.nl/2005/12/compositio ... and-morons.
Odyssey
энтузиаст
 
Сообщения: 580
Зарегистрирован: 29.11.2007 17:32:24

Re: Строковый зоопарк

Сообщение SII » 19.08.2011 16:24:21

Odyssey писал(а):Смотря что понимать под "символами". Если, например, вас устроит то, что в одной из нормальных форм Юникода
Й -- это два "символа" -- И и крышечка, то можно.


Именно это я и имел в виду: то, что считается символом с точки зрения Юникода.
SII
новенький
 
Сообщения: 64
Зарегистрирован: 24.06.2007 17:15:09
Откуда: Зеленоград

Re: Строковый зоопарк

Сообщение and » 19.08.2011 17:36:54

Vadim писал(а):Так Вы сами то и используйте какой-нибудь один подход к PChar, тогда и не будет никакой путаницы.
Сам-то я могу. Но мне приходится работать и с данными, приходящими со стороны. И, как я ужЕ писАл, я не могу заставить всех, передающих мне этот злополучный pChar, выбрать какой-то один. Так что проблема именно
Vadim писал(а):языковая
, и заключается она в недостаточно строгой (вот уж не думал, что про Паскаль такое скажу) типизации указателя.

Odyssey писал(а):только освобождать предыдущий PChar нужно тем же методом, которым он создавался
И рад бы в рай, да грехи не пускают :-) Я бы с удовольствием делал "как нужно", если б мог узнать, как этот pChar создавался. Будет время - попробую написАть обёртку, ковыряющую менеджер хипа на предмет принадлежности и начала блока: по крайней мере, буду знать, это динамический pChar или ссылка на статический массив. Будет imho тормозить, но другого пути не вижу.
Odyssey писал(а):Может быть потому, что способов освобождения PChar -- несколько, и такая функция не знала бы какой из них использовать?
Ну, если уж даже RTL этого выяснить не может, что ж о приложении говорить...

Добавлено спустя 25 минут 55 секунд:
Маленький вопрос вдогонку: для shortString сборка мусора есть? (вроде ж у них нет счётчика ссылок в самОй строке).
Аватара пользователя
and
постоялец
 
Сообщения: 124
Зарегистрирован: 16.09.2009 17:11:01
Откуда: г. Гомель, Беларусь

Re: Строковый зоопарк

Сообщение kipar » 19.08.2011 18:29:59

При работе с данными "со стороны" я бы копировал их сразу в "свой" string и дальше работал только с ним. Но это если производительность не критична.

Если надо передать строку в функцию dll, то достаточно PChar(s), т.к. за время работы функции строка никуда не денется.

shortstring передаются копированием, им счетчик ссылок не нужен (это фактически просто array[1..255] of char с байтом длины).
kipar
новенький
 
Сообщения: 78
Зарегистрирован: 04.03.2010 12:15:54

Re: Строковый зоопарк

Сообщение MageSlayer » 19.08.2011 19:18:29

Что-то странно, что никто задается вопросом как кроссплатформенно нормализировать строки в fpc/lazarus.
Самому пока не очень-то надо, но вопрос остается.

Тупым поиском по исходникам fpc находится только какая g_utf8_normalize.
packages/gtk2/src/glib/gunicode.inc:236: g_utf8_normalize

Есть у кого наработки?
Надо же как-то сравнивать строки, да поиск подстроки в utf8 тоже никто еще не отменял!
MageSlayer
постоялец
 
Сообщения: 216
Зарегистрирован: 07.09.2006 12:30:44

След.

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

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

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

Рейтинг@Mail.ru