Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2003.01.06;
Скачать: [xml.tar.bz2];

Вниз

Глупый вопрос: Pchar ->string   Найти похожие ветки 

 
pavel_ak   (2002-12-14 21:04) [0]

Была же простая функция для перевода PChar в string. Но я ее забыл. В helpe искал - не нашел. Может кто вспомнет навскидку?


 
Anatoly Podgoretsky   (2002-12-14 21:09) [1]

Конечно, для этого функция не требуется.


 
pavel_ak   (2002-12-14 21:11) [2]

-??? (а подробнее?)


 
TTCustomDelphiMaster   (2002-12-14 21:13) [3]

string1 := pchar1;


 
xyz   (2002-12-14 22:09) [4]

Этот вопрос стар как сам делфи )))
var ch : PChar;
str : string;
ch := PChar(str);

А стринг из ПЧара получать... смех...


 
Набережных С.   (2002-12-14 22:34) [5]

>TTCustomDelphiMaster © (14.12.02 21:13)
Это только, если PChar указывает на строку, заканчивающуюся нулем, что не есть непреложный факт.

>pavel_ak © (14.12.02 21:11)
SetString, например.


 
Anatoly Podgoretsky   (2002-12-14 23:02) [6]

Так PChar согласно справочной системы Дельфи

PChar is a pointer to a null-terminated string of 8-bit characters.

То есть в Дельфи другие варианты не рассматриваются и как PChar не считаются.


 
TTCustomDelphiMaster   (2002-12-14 23:21) [7]

Набережных С.
Я исходил из того, что в 99,999% случаев PChar указывает на строку, заканчивающуюся нулем.


 
Набережных С.   (2002-12-14 23:21) [8]

>Anatoly Podgoretsky © (14.12.02 23:02)
Ну это уже софистика:)


 
Набережных С.   (2002-12-14 23:27) [9]

TTCustomDelphiMaster © (14.12.02 23:21)
Ну, насчет 99,999% ты явно погорячился:)

var
PC: PChar;
S:string;
Ch: array[0..2]of Char;
Ch1: array[0..2]of Char;
begin
Ch:="ABC";
Ch1:="DEF";
PC:=@Ch;
S:=PC;
ShowMessage(s);
end;

Не реально?


 
TTCustomDelphiMaster   (2002-12-14 23:32) [10]


> Не реально?

Нет. Какой смысл в этом. Где реально применяются указатели PChar как указатель на строку не завершающуюся #00. Как узнавать ее длину?


 
Набережных С.   (2002-12-14 23:37) [11]

Ну не реально, так не реально. Смыслов много, но это для меня. Настаивать я не буду.


 
Fantasist   (2002-12-15 23:05) [12]


> Это только, если PChar указывает на строку, заканчивающуюся
> нулем, что не есть непреложный факт


Если это С-строка не заканчивающаяся нулем, то это уже не строка, а просто указатель на нечто. Чтобы она была строкой (С-строкой), она обязанна заканчиваться на 0.


 
Anatoly Podgoretsky   (2002-12-15 23:10) [13]

TTCustomDelphiMaster © (14.12.02 23:32)
PChar можно использовать не только как указатель на ASCIIZ строку, а на что угодно, только работать надо не как со строкой
Иногда это удобно из за поддержки адресной математики, как использование string не для хранения строк, а двоичных данных, из за великолепного управления памятью.


 
Snap   (2002-12-15 23:20) [14]

Насколько я знаю, strPass или StrPCopy делает как раз то что тебе надо!.


 
Sha   (2002-12-15 23:33) [15]

Иногда, например, бывает надо обработать целочисленный массив побайтно - PChar незаменим.


 
Snap   (2002-12-15 23:34) [16]

Лучше всего природу Pchara понять поможет его объявление - ^char.


 
Jeer   (2002-12-16 00:16) [17]

Sha © (15.12.02 23:33)

Возможно, если забыть о предопределенных

IntegerArray = array[0..$effffff] of Integer;
PIntegerArray = ^IntegerArray;
PSmallInt = ^SmallInt;
PInteger = ^Integer;
PSingle = ^Single;
PDouble = ^Double;
PDate = ^Double;
PDispatch = ^IDispatch;
PPDispatch = ^PDispatch;
PError = ^LongWord;
PWordBool = ^WordBool;
PUnknown = ^IUnknown;
PPUnknown = ^PUnknown;
PByte = ^Byte;
PPWideChar = ^PWideChar;


 
xyz   (2002-12-16 00:41) [18]

из-за String и PChar столько шуму...


 
Sha   (2002-12-16 09:16) [19]

2 Jeer © (16.12.02 00:16)
У меня случается, что в строках String лежат целые числа.
Для их побайтной обработки, например, так:
(a+i)^:=(a+i+1)^ xor (a+i+2)^ xor (a+i+3)^;
логичнее использовать PChar, а не PByte.
Здесь все a - байты целого числа, являющегося элементом
массива с индексом, равным i div 4.



 
Sha   (2002-12-16 09:19) [20]

2 xyz © (16.12.02 00:41) и других "продолжающих".

Обсуждая PChar, мы забыли про ребенка.

Сначала маленькая загадка.
Попробуйте угадать, что выведет на экран простейшая программа:

procedure TForm1.Button4Click(Sender: TObject);
var
s, t, r: string;
pc: PChar;
begin
s:="qwerty";
t:="qwerty";
r:="qwerty";
pc:=@s[1]; pc^:="-"; ShowMessage(r);
pc:=PChar(t); pc^:="-"; ShowMessage(r);
end;

Теперь пространный ответ для начинающих.
Разработчики Дельфи "улучшая" старый короткий строковый тип, почему-то думали,
что нам вечно будет не хватать памяти и вынудили программистов пользоваться
скрытым механизмом подсчета ссылок на строки. Может это и здорово, но в моих
программах почему-то раз в 100 чаще оказывается, что ссылки посчитывать
как раз не надо.

Хотя бы дали возможность выбора или ввели новый тип. В результате этого
идиотизма стало просто невозможно написать эффективную программу, работающую
с отдельными символами строк (типа String, разумеется).
Где выход,- спросите вы. Да, да, вы знали: надо использовать PChar.
При его использовании в подобных программах эффективность возрастает в десятки
раз: не надо подсчитывать ссылки, не надо получать уникальные строки.

Пример приводить не буду. Тут пару дней назад кто-то не сделал домашнего
задания (перебор всех слов из заданного множества букв).
Если надо, найдите его - там есть пример. Если сам найду, подниму.

А как же обещанный ответ?
После выполнения первых трех операторов все строки (s, t, r) будут не просто равны.
Они будут одной строкой, использованной 3 раза, т.е. будут располагаться по одному адресу.
Первый ShowMessage покажет "qwerty", т.к. в результате оператора pc:=@s[1]
произойдет обращение за уникальной строкой и s будет располагаться уже не там,
где r и t, хоть они и будут оставаться равными. И, значит, изменение первого
символа строки s никак не повлияет на строку r.
Второй ShowMessage покажет "-werty", т.к. pc:=PChar(t) не обращается за
уникальной строкой, и, изменяя t, мы меняем r.

Почувствуйте разницу, и пребудет с вами сила.



 
Ihor Osov'yak   (2002-12-16 10:38) [21]

2 Sha © (16.12.02 09:19)

У Вас, во первых, присутствует как минимум, две ошибки.
Обо всем попорядку.
Во первых: строки-константы размещаются в учаске памяти, имеющей атрибут рид-онли и механизм подсчета ссылок для них блокирован (запустите на трассирование фрагмент

s:="qwerty";
t:="qwerty";
r:="qwerty";

в режиме "CPU" (там, где дисассемблер - Ctrl+Alt+C), одновреммено проссматривая участок памяти, где живет наша "qwerty" - понятное дело, прихопив восемь байт перед началом тела строки... Вы увидите, что счетчик юзаний не меняется, он вообще установлен в $FFFFFFFF...

Вторая - вылет в следуещем фрагменте:

pc:=PChar(t); pc^:="-"; ShowMessage(r);
Здесь оператор присваивания вызовет ошибку. Ибо pc будет указывать та "оригинальную строку", размещенную в "рид-онли" участке памяти...

Ps, в чем с Вами согласен, что борланд немного перемудрил со строками... Хотя вряд-ли можно было придумать что-либо лучшее.
А если вспомнить, что string=AnsiString=поинтер на структуру - то все встает на свои места... Жаль только, что практически все книги не уделяют должного внимания этому вопросу ... Отсюда и куча непоняток в тех начинающих, которые начинают выходить из уровня "ламерства"... А если чел еще не дружит Ctrl+Alt+C - проблема для него может быть очень серьезная ...

ЗЫ2 - а пимер Вы действительно хорошийц привели ... Если не брать во внимание нескольких тех неточностей, упрмянутых выше




 
han_malign   (2002-12-16 10:50) [22]

2 Sha - ошибочка у вас закралась и вы ввели в заблуждение публику
procedure TForm1.Button4Click(Sender: TObject);
var
s, t, r: string;
pc: PChar;
begin
s:="qwerty";
t:="qwerty";
r:=t; //!!! r:="qwerty";
pc:=@s[1]; pc^:="-"; ShowMessage(r);
pc:=PChar(t); pc^:="-"; ShowMessage(r);
end;
- тогда будет так как вы сказали, но только для случая прямого приведения типов(что всегда делается исключительно на свой страх и риск), если сделать t[1]:="-" то для t автоматически будет выделен новый блок памяти и скопирована страрая информация.
!!!!ВНИМАНИЕ - ДЛЯ ОТКРЫТЫХ МАССИВОВ, ПРИ ИЗМЕНЕНИИ, АВТОМАТИЧЕСКОЕ РАЗДЕЛЕНИЕ ССЫЛОК ПРОИСХОДИТЬ НЕ БУДЕТ - это специально описано в хелпе, к открытым массивам надо изначально относиться как к указателям(причем Length(OpenArray)=0 можно проверять и таким способом - OpenArray=nil), только со своими функциями управления памятью и автоматическими приведением типа и адрессацией.
З.Ы. Честно говоря не понимаю возмущения, за вас сделали всю работу по управлению памяти, причем интеллектуальнальному управлению(программа активно работающая с string, IMHO надежней чем с PCHAR, поскольку когда вы отладите свою программу по поводу утечек памяти - не известно, а string-и отлажены уже давно и проверены на тысячах комерческих проектах). String - это тот-же PChar (s[Length[s]+1]=#0 - всегда), только добавлено неявное поле DWORD(pointer(DWORD(s)-4)^)=Length(s), плюс механизм ссылок. Для явного разделения ссылок достаточно сделать SetLength(t,Length(t)).
З.З.Ы. Причем механизм подсчета ссылок это не эксклюзив string-ов, этот механизм изначально зашит в Delphi-ийский менеджер кучи, только не везде используется(string, Interface). Так-что работая с PChar через GetMem/FreeMem/New/Dispose - вы все равно его используете, но в холостом режиме.
З.З.З.Ы. Причем работает и WideString:=String и String:=WideString, только что убедился что даже корректно(для интернацинальных - кодировку в старшем байте проставляет).


 
KSergey   (2002-12-16 11:11) [23]

Спасибо всем! Для меня было очень познавательно.

PS: люди, откуда вы все знаете?? впрочем, это риторический вопрос.


 
Sha   (2002-12-16 11:24) [24]

2 Ihor Osov"yak © (16.12.02 10:38)
2 han_malign © (16.12.02 10:50)

А вы попробуйте исполнить мой код, поставьте брекпойнт в начале процедуры, посмотрите память, а потом говорите про ошибки.


 
Sha   (2002-12-16 11:31) [25]

2 han_malign © (16.12.02 10:50)
Я лишь описал некоторые тонкости применения строковых типов.
Никакого возмущения нет и в помине. Дельфи форэва !!!
Просто хотелось бы иметь длинные строки без подсчета ссылок, вот и все.


 
Ihor Osov'yak   (2002-12-16 11:35) [26]

2 Sha © (16.12.02 11:24)

Мил человек, а я так и делал, перед тем как писать сюда...
Хотя что там не все чисто догадался и теоритически ... :-)






 
vedmed   (2002-12-16 12:21) [27]

2 Sha ©

В WideString нет подсчета ссылок, для типа string есть процедура UniqueString


 
Ihor Osov'yak   (2002-12-16 12:23) [28]

В дополнение :-)

> Просто хотелось бы иметь длинные строки без подсчета ссылок,
> вот и все.



А раскажите, пожалуйста, как себе Вы представляете реализацию

s:=s+"qwerty" где s - длинная строка без механизма подсчета ссылок и с кооректным освобождением памяти от "старого екзампляра" тела строки...

Зы и еще - перед тем как кому-то советовать прогнать Ваш код в отладчике, следовало бы это делать самому ...



 
Ihor Osov'yak   (2002-12-16 12:31) [29]

сорри, в (16.12.02 12:23) подразумевается конечно не widestring :-)


 
Danlicha   (2002-12-16 12:42) [30]

Да, чуваки, клёво! И, кстати, никто не отменял ShortString - я его использую везде, где только можно, т.к. глупо для строки в несколько символов выделять большой стринг, с восьми или двеннадцитибайтным заголовком. И не медленне работает, чем сишные. Но надёжно.


 
Sha   (2002-12-16 12:50) [31]

2 Ihor Osov"yak ©
>pc:=PChar(t); pc^:="-"; ShowMessage(r);
>Здесь оператор присваивания вызовет ошибку. Ибо pc будет
>указывать та "оригинальную строку", размещенную в "рид-онли"
>участке памяти...

У меня не вызывает :)

>А раскажите, пожалуйста, как себе Вы представляете реализацию
>s:=s+"qwerty" где s - длинная строка без механизма подсчета
>ссылок и с кооректным освобождением памяти от "старого
>екзампляра" тела строки...

Я думал, все знают это.
Выделяем память для t, выполняем t:=s+"qwerty", освобождаем s,
далее t называем s.






 
Sha   (2002-12-16 13:08) [32]

2 Ihor Osov"yak ©
Насчет счетчика юзанья.
Исправьте начало так:
---
s:="qwerty"; s[1]:="q";
t:=s;
r:=s;
---
Теперь счетчик меняется как положено?
Про счетчик я сказал просто так - для информации.
Я вовсе не утверждал, что такое поведение программы зависит от счетчика. Я даже не говорил, что он равен трем. Будьте внимательны, мил человек.
А утверждал я вот что: операторы pc:=@s[1] и pc:=PChar(t) работают по-разному - одному нужна уникальная строка, другому нет.
З.Ы. Я всегда все гоняю под отладчиком, иначе откуда мне это знать.


 
Ihor Osov'yak   (2002-12-16 15:35) [33]

2 Sha © (16.12.02 12:50)

Ну и вы любитель разводить дисскусию на пустом месте + талант перекручивать слова собеседника ..

у меня было:
s:=s+"qwerty" - то есть тривиальное соединение строк без декларации промежуточной переменной и ручной работы по освобождению памяти.
Вы почемуто начали комментировать реализацию с промежуточной переменной t и с ручками по памяти. Юзайте себе на здоровье PChar и занимайтесь мазохизмом с ручным выделением/освобождением памяти везде где это только возможно... Одно из главных преимуществ борландовской реализации string - то что код с операциями соединения строк очень прозрачен и компактен, без рутинной работы по управлению выделениею и освобождению памяти, что невозможно реализовать без счетчика использований.. А если уже вас понесло на "силовое" приведение типов - так вы должны соображать,что делаете... Не говоря уже о том, что нужно очень подумать, перед тем как такое делать....




> У меня не вызывает :)


D5, sp1... вы, возможно юзаете версию компилятора, которая размещает строки-константы в памяти с r/o, что, если быть очень дотошным, не совсем корректно... Да, и если у вас это действительно работает - можете запомнить на всю последующую жизнь, как пример плохого кода, который может вызывать проблемы под разными версиями комполяторов..



> Исправьте начало так:


Оригинально-с... Я не спрашивал вас, как написать, чтобЫ счетчик заработал. Я обратил только внимание на то, что в коде, который привели вы, счетчик вообще не юзается, и это есть корректно, ибо не будем же удалять строку-константу, которая "живет" в образе PE, загруженном в память...


> pc:=@s[1] и pc:=PChar(t) работают по-разному


И правильно делает. В первом случае, вы запрашиваете указатель на элемент строки(пускай и первый), то есть заявляате, что собираетесь потенциально измееять его. И целиком естественно, что компилятор для вас строит копию начальной строки, которая еще юзается какими-то другими обьектами программы, чтобы застраховатся от изменения оригинальной строки, которая не есть в монопольном использовании. То есть реализация кода в этом случае есть абсолютно корректной...
Во втором случае - pc:=PChar(t) - присваивание указателя с "силовым" приведением типа. Последствия за использование - полностью на кодере...

Зы - если под отладчиком в контекте разговора вы понимаете отладку на уровне дизассемблера - то очень странно, что вы ожидаете, что pc:=@s[1] и pc:=PChar(t) сгенерят вам одинаковый код. Ибо это вещи совершенно разные. Если Вы работаете на уровне символьного отладчика - не поленитесь, углубтесь на уровень диссамилерного кода (предварительно несколько узучив ассемблер) -
и на многое у вас будет точка зрения гораздо ближе к истинной ...


 
Ihor Osov'yak   (2002-12-16 15:39) [34]

Должно быть:
которая не размещает строки-константы в памяти с r/o
что, если быть очень дотошным, не совсем корректно...


 
Anatoly Podgoretsky   (2002-12-16 15:46) [35]

Второй вариант еще сложнее, пусть S := "", тогда функция вместо передачи nil, как это было бы для неициализированной PChar переменной выдаст из кодового сегмента адрес нулевой строки, защитив тем самым некоторые WinApi функции и в противоположном случае выдаст адрес s[1], ошибки не произойдет.



 
Ihor Osov'yak   (2002-12-16 15:47) [36]

2 2 Sha © (16.12.02 12:50)

Еще две цитаты:

от Sha © (16.12.02 09:19)


> Они будут одной строкой, использованной 3 раза, т.е. будут
> располагаться по одному адресу.

от Sha © (16.12.02 13:08)

Я даже не говорил, что он равен трем. Будьте внимательны, мил человек.


Это я к тому, что внимательно читаю постинги, на которые собираюсь дать критический ответ. Я, между прочим, не оспаривал тот факт, что строка заюзана три раза. Я обратил только внимание на то, что для строк-констант, счетчик использования блокирован - см Ihor Osov"yak © (16.12.02 10:38).



 
Anatoly Podgoretsky   (2002-12-16 15:48) [37]

Надеюсь, что никто не будет оспаривать, что "" и nil для PChar строк это не одно и тоже, кстати на этом часто горят, при передаче в WinApi функцию как константы


 
Ihor Osov'yak   (2002-12-16 15:49) [38]

2 Anatoly Podgoretsky © (16.12.02 15:46)

Маестро, Вы как всегда, правы.. :-)


 
Sha   (2002-12-16 16:15) [39]

2 Ihor Osov"yak © (16.12.02 15:35)

> Ну и вы любитель разводить дисскусию на пустом месте + талант перекручивать слова собеседника ..

Зачем же вешать ярлыки? Будьте корректнее.

> Вы почемуто начали комментировать реализацию с промежуточной
> переменной t и с ручками по памяти... Не говоря уже о том, что
> нужно очень подумать, перед тем как такое делать....

Я начал комментировать возможную реализацию желаемого типа на
уровне компилятора. Жаль, что вы не поняли.

> D5, sp1... вы, возможно юзаете версию компилятора, которая
> размещает строки-константы в памяти с r/o, что, если быть очень
> дотошным, не совсем корректно...

Это в Борланд :)

> Да, и если у вас это действительно работает - можете запомнить
> на всю последующую жизнь, как пример плохого кода, который
> может вызывать проблемы под разными версиями комполяторов..

С чего вы взяли, что я этого не знаю. Более того, я делюсь своими знаниями с вами.

> Я обратил только внимание на то, что в коде, который привели
> вы, счетчик вообще не юзается, и это есть корректно, ибо не
> будем же удалять строку-константу, которая "живет" в образе PE,
> загруженном в память...

И это мне известно. Я тоже это подчеркивал.

>> pc:=@s[1] и pc:=PChar(t) работают по-разному
> И правильно делает...

Полностью согласен. И тоже знаю ПОЧЕМУ.


>Зы - если под отладчиком в контекте разговора вы понимаете
>отладку на уровне дизассемблера - то очень странно, что вы
>ожидаете, что pc:=@s[1] и pc:=PChar(t) сгенерят вам
>одинаковый код. Ибо это вещи совершенно разные.

Я и не ожидаю. И не хочу, чтобы другие ожидали. Как раз это
я и сказал в самом начале, приведя ответ на свою загадку.

>Если Вы работаете на уровне символьного отладчика - не
>поленитесь, углубтесь на уровень диссамилерного кода
>(предварительно несколько узучив ассемблер) -
>и на многое у вас будет точка зрения гораздо ближе к истинной ...

Почему вы решили, что я не знаю ассемблер. Вы телепат?
Мы оба понимаем, о чем речь. Не надо цепляться.
Уважайте чужие знания.


 
Sha   (2002-12-16 16:30) [40]

2 2 Ihor Osov"yak © (16.12.02 15:47)

>Еще две цитаты:

>от Sha © (16.12.02 09:19)

>> Они будут одной строкой, использованной 3 раза, т.е. будут
>> располагаться по одному адресу.

>от Sha © (16.12.02 13:08)

>>Я даже не говорил, что он равен трем. Будьте внимательны, мил человек.

Это действительно так!!! Мы имеем три строки с одним и тем же значением. И ни слова не сказано про значение счетчика использований для этой константы.

> Это я к тому, что внимательно читаю постинги, на которые
> собираюсь дать критический ответ. Я, между прочим, не
> оспаривал тот факт, что строка заюзана три раза. Я обратил
> только внимание на то, что для строк-констант, счетчик
> использования блокирован - см Ihor Osov"yak © (16.12.02 10:38).

Это известный факт, я с этим согласен.



Страницы: 1 2 вся ветка

Форум: "Основная";
Текущий архив: 2003.01.06;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.58 MB
Время: 0.009 c
14-15294
denisac
2002-12-04 10:38
2003.01.06
Работа началась!!!


4-15355
sdram
2002-11-18 17:46
2003.01.06
Как узнать текущую OS?


14-15276
GROL
2002-12-15 23:09
2003.01.06
Delphi 7 - XP/2


14-15249
race1
2002-12-10 07:59
2003.01.06
деньги


3-14931
atmamont
2002-12-12 00:47
2003.01.06
Посоветуйте что использовать для отчетов





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский