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

Вниз

PChar   Найти похожие ветки 

 
SPeller   (2002-07-25 12:56) [0]

Всем доброго времени суток! Что-то я вроде бы и прочитал хелп по null-terminated string"ам, но всё-равно остались сомнения по такому вопросу: как правильно сделать так, чтобы процедура изменяла значение параметра PChar?

В примере из хелпа не надо указывать слово var для того чтобы изменить значение параметра, поэтому я объявляю свою процедуру так:

procedure MyProc(S1,S2:PChar);

Изменить надо оба параметра. Но когда я делаю в процедуре

S1:=PChar(Src); ,где Src имеет тип String

компилятор выдаёт Value assigned to S1 never used и поэтому по всей видимости, вследствие оптимизации выкидывает этот код.
Как мне правильно сделать присвоение чтобы получить нужный результат?

И ещё вопрос. Почти во всех функциях по работе с PChar говорится что они не проверяют размер самой строки и делают своё дело куда придётся, но я не нашёл функцию, которая задаёт длину строки. Для String достаточно было сделать SetLength, а вот для PChar как сделать подобное? И надо ли вообще это делать? В хелпе говорится что обычное присвоение вроде S:="Hello word" автоматически делает копию текста и устанавливают указатель в начало. А если в правой части оператора присваивания стоит тоже PChar или что-то другое? Почему не нравится S1:=PChar(Src);? И как обстоит дело с высвобождением памяти, занимаемой PChar-строкой?
Вообще мне не понятен механизм, по которому осуществляется работа с PChar"ами. Как выделяется память, как освобождается, ведь это по существу просто указатель.

Прошу помощи в данном вопросе, а то в хелпе инфы по нему как кот наплакал.


 
MBo   (2002-07-25 13:30) [1]

про первый вопрос с приведением типов поподробнее расшифруй, что именно требуется

PChar - обыкновенный указатель, для выделения памяти надо делать, скажем, GetMem, длина такой строки определяется
только нахождением нулевого символа. Освобождение памяти соответственно Freemem.


 
Skier   (2002-07-25 13:32) [2]

>SPeller
Можно ещё посмотреть :

StrAlloc
StrNew
StrDispose


 
Толик   (2002-07-25 13:33) [3]

При работе с pchar всегда следует помнить о том, что это УКАЗАТЕЛЬ на char, а значит и работать с ним надо как с указателем:
Веделям память - записываем значение ... - освобождлаем память.

теперь, что касается примера:

procedure MyProc(S1,S2:PChar);
begin
S1 := PChar(Src);
end;

В данном примере в функции MyProc создаётся КОПИЯ передаваемого значения, т.е. копируются 4 байта указателя на char. Естественно, что все изменения этого указателя будут видны только внутри этой ф-и. Для получения желаемого эффекта необходимо не переприсваивать значение адреса, хранящегося в S1, а производить запись ПО АДРЕСУ, лежащему в S1.
Для данного случая я бы посоветовал

function StrCopy(Dest: PChar; const Source: PChar): PChar;


Задание длины строки - есть выделение под неё памяти, например function StrAlloc(Size: Cardinal): PChar;
где Size - кол-во символов, без последнего "0", которым заканчиваются все строки pchar.


 
SPeller   (2002-07-25 14:09) [4]

Тогда почему при обычном присваивании не надо ничего самому выделять? И ещё, почему в хелповском примере для переменной Result ничего не выделяется, а идёт простое присвоение?



2 MBo © (25.07.02 13:30)

Мне надо в вызывающую программу передать изменённый параметр S1. Например я процедуре передаю "C:\WINDOWS", а она мне возвращает "C:\WINDOWS\SYSTEM". В таком вот духе. Где-то внутри процедуры я постепенно в переменной String собираю строку, которую надо вернуть, а потом возвращаю. Как если бы было
procedure (var S:string); , а в теле S:="C:\WINDOWS\SYSTEM".


 
Толик   (2002-07-25 15:24) [5]

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


 
SPeller   (2002-07-25 18:16) [6]

Всем спасибо. Какие же хелпы бестолковые в некоторых отношениях бывают!! :)


 
Anatoly Podgoretsky   (2002-07-25 20:28) [7]

Мне кажется, что с хелпами все в порядке


 
SPeller   (2002-07-26 02:53) [8]

2 Anatoly Podgoretsky © (25.07.02 20:28)

В общем случае да. Но вот мне кажется, что информация, содержащаяся в хелпе, должна восприниматься после одного-двух-трёх прочтений, а не после детальнейшего изучения и анализирования каждого предложения из двух-трёх десятнков топиков.


 
Александр Малыгин   (2002-07-26 12:16) [9]

Люди! Будьте проще!

В Object Pascal тип string настолько совместим с pchar, что можно делать присваивания туда и обратно без приведения типов и использования функций. Компилятор все понимает и сам копирует содержимое строки. Разумеется, память должна быть уже выделена.

var S : string;
P : pchar;
...
P := S;
S := P;


P.S. Речь, конечно, идет о длинных строках (AnsiString, не ShortString).


 
MBo   (2002-07-26 12:24) [10]

>Александр Малыгин
конечно, часто этого достаточно, но беда случится при изменении (с реаллокацией) таким образом полученных строк


 
Anatoly Podgoretsky   (2002-07-26 12:26) [11]

SPeller © (26.07.02 02:53)
Ты заставил меня засомневаться в Борланде, проверил я хелп, все в порядке.

A PChar is a pointer to a null-terminated string of characters of the type Char.

Сказано абсолютно все, ничего не удаяно и добавить нечего, рсталось у меня обно сомнение, на этот раз не на Борланда, а на тебя, может ты не знаешь английского языка в объеме достаточном для программирования, тогда вот передод:

PChar является указателем на строку символов типа Char, ограниченную нулем.


От переводчика:
Символ ноль в Паскале указывается как #0 и имеет значение $0, знак ноль пригоден для указания любых символов в диапазоне от 0 и выше.



 
Александр Малыгин   (2002-07-26 12:29) [12]

Отнюдь!

Таким образом полученная строка ничем не отличается от S := "Константа";


 
MBo   (2002-07-26 12:43) [13]


p:pchar;
s:string;

procedure TForm1.Button1Click(Sender: TObject);
begin
s:="qqq";
p:=pchar(s);
s:="www";
showmessage(s+" "+p);
end;


 
Александр Малыгин   (2002-07-26 13:14) [14]

TO: MBo

Ваш код не корректен, поскольку вы копируете указатель:
p:=pchar(s);

Я же говорил, что не надо приводить тип, если цель - скопировать строку. Только указатель pchar должен быть инициализирован.
Пример:

var Buf : array[byte] of char; // буфер из 256 символов
P : pchar;
S : string;
begin
p := @Buf; // указатель инициализирован
s:="qqq";
p:=s; // копирование строки
s:="www";
showmessage(s+" "+p); // здесь будет "www qqq"
end;


 
MBo   (2002-07-26 13:24) [15]

такое
p:=s;
мне компилятор запрещает

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


 
Александр Малыгин   (2002-07-26 13:42) [16]

TO: MBo

Извиняюсь, прогнал :-(

Но S := P работает!

А наш пример перепишем так:

begin
s:="qqq";
p := StrPCopy(@Buf, s); // копирование строки в буфер и инициализация указателя
s:="www";
showmessage(s+" "+p); // здесь будет "www qqq"
end



Еще интересный факт.
Типы WideString и AnsiString совместимы по присваиванию, сравнению и передаче в качестве const параметра.


 
MBo   (2002-07-26 13:46) [17]

Еще любопытный пример граблей

procedure TForm1.Button1Click(Sender: TObject);
var
s:String;
begin
SetLength(s,100);
GetWindowText(Handle,PChar(S),100);
S:=S+" is My Caption";//не сработает
// S:="My Caption is: "+s;//а так можно
Caption:=S;
end;


 
SPeller   (2002-07-26 13:51) [18]

2 Anatoly Podgoretsky © (26.07.02 12:26)

Вот такая цитата:
var P: PChar;
...
P := "Hello world!";

points P to an area of memory that contains a null-terminated copy of “Hello world!”


Здесь ведь не надо ничего инициализировать, автоматически создаётся копия текста и ставится указатель туда. Если посмотреть практически, то мы присваиваем указателю строку. Такое возможно? Попрбуйте проделать подобное с другими типами указателей. Ничего акромя Incompatible types не выйдет. Значит это уже не простой указатель и компилятор часть забот берёт на себя. Это у заставило меня вообще задать вопрос, чтобы узнать точно, что к чему. Потому как в хелпе кроме того что это указатель на строку, заканчивающуюся на #0 ничего нет. (Да это я давно уже знаю)

> тогда вот передод ...

Знаете, обойдусь без посторонней помощи в таком вопросе. В крайнем случае словарь возьму. А решать, достаточно ли у меня знаний для программирования извините, не вам, и уж точно не по признаку знания английского. Да и откуда вам знать, каковы они?

ЗЫ: Кстати, это был почти самый длинный постинг от вас, обычно пара слов и всё, а тут на те, прорвало.... :)


 
Anatoly Podgoretsky   (2002-07-26 13:52) [19]

MBo © (26.07.02 13:24)
И правильно делает, ну откуда ему знать, что ты хочешь присвоить адрес или содержимое этого адреса.


 
Alx2   (2002-07-26 14:00) [20]

>Anatoly Podgoretsky © (26.07.02 13:52)
>откуда ему знать, что ты хочешь присвоить адрес
>или содержимое этого адреса.
Из типов переменных, естественно.


 
Игорь Шевченко   (2002-07-26 14:06) [21]

Кстати, PChar(AnsiString) - это вызов функции _LStrToPChar :-)


 
Толик   (2002-07-26 14:20) [22]

to SPeller © (26.07.02 13:51)
Честно говоря, есть за Делфёй такой грешок - выполнение разных действий на "заднем плане", к которым не получить доступ (например то же приведение типов из string в pchar), наличие всяких системных фунцций и пр.
С этим конечно можно смирится, но неприятный осадок недоверия остаётся...


 
SPeller   (2002-07-26 16:09) [23]

2 Толик © (26.07.02 14:20)

Вот-вот, из-за чего и весь вопрос.


 
Anatoly Podgoretsky   (2002-07-26 16:27) [24]

Alx2 © (26.07.02 14:00)
Правильно, PChar это указатель, string это как минимум два указателя, сообственно сам стрниг и его содержимое, второго может не быть, а работать должно, оператор str^ как бы не применим в этом случае
В случае применения приведения, гарантирует работоспособность WinApi функции, в зависимости от содержимого будет выдано или содержимое на PChar соместимое и указатель на PChar соместимую строку, так как S := "", а не nil указатель, котрый может привести в растройство WinApi.


 
Толик   (2002-07-26 17:24) [25]

М-да. похоже тема задела за живое :)))


 
Anatoly Podgoretsky   (2002-07-26 17:29) [26]

Да ничего особого, просто многие не понимают что такое PChar, откуда он взялся м как с ним работать, отсюда постоянные ошибки и требуется помощь от Пушкина, разбаловали строки в Паскале.



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

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

Наверх





Память: 0.65 MB
Время: 0.042 c
3-23953
the-best-officeman
2002-07-18 21:06
2002.08.08
for i := 0 to table1.RecordCount-1 do begin


7-24240
Евгений!
2002-03-06 19:44
2002.08.08
Как добавить свой пункт в контекстное меню IE и ...


6-24164
XobbuT
2002-05-25 19:54
2002.08.08
Уважаемые Мастера, помогите с вопросом: Как отловить входящие пак


14-24205
Ильдар
2002-07-13 13:51
2002.08.08
Где?


3-23958
Пастор
2002-07-18 18:46
2002.08.08
Как динамически создать вычисляемое или lookup поле ?





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский