![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Функция копирования PChar в string [D6, D7, Win2k, WinXP]
MetalFan © (2006-10-16 17:57:00)что необходимо:
1) копировать содержимое string в Pchar
2) выделять/перевыделять память под PChar
3) очищать PChar, если длинна string = 0;
вот написана такая функция
function SetPChar( var APChar: PChar; const ACopyString: string): PChar;
var
lLenStr: Integer;
begin
Result := nil;
lLenStr := Length(ACopyString);
if (APChar = nil) and ( lLenStr= 0) then Exit;
if lLenStr = 0 then
begin
FreeMem( APChar{, 0});
APChar := nil;
end
else
begin
ReallocMem( APChar, lLenStr + 1);
//Result := StrLCopy(APChar, PChar(ACopyString), lLenStr);
CopyMemory( APChar, @ACopyString[1], lLenStr);
APChar[lLenStr] := #0;
end;
Result := APChar;
end;
оцените ее правильность %) что-то никак не соображу, есть ли тут косяки...
Anatoly Podgoretsky (2006-10-17 10:05:00) [1]
> А действительно, для чего понадобилось использовать и то
> и другое??
В Дельфи PChar использовать не требуется. String полностью совместим с PChar
> только для Win-API ф-ий, и то, чаще всего, можно не явно
> использовать.
И там не требуется, а если функция возращает PChar, то никому не запрещено сделать S := PChar
icWasya (2006-10-17 09:51:00) [2]>>зачем вообще упали этот PChar в Делфи
А действительно, для чего понадобилось использовать и то и другое??
Eraser (2006-10-16 23:43:00) [3]в догонку:
зачем вообще упали этот PChar в Делфи... не зря есть намного более удобный типа - string. С ним и надо работать, а PChar - только для Win-API ф-ий, и то, чаще всего, можно не явно использовать.
MetalFan (2006-10-16 21:43:00) [4]
> Для этого обычно используют TStringList.
есть необходимость использовать TList)
но спасибо за совет ;)
Leonid Troyanovsky (2006-10-16 20:20:00) [5]
> MetalFan © (16.10.06 20:12) [22]
> вне функции имеем TList, в котором хранятся таким образом
> выделяемые PChar'ы...
Для этого обычно используют TStringList.
Если, вдруг, потребуются PChar делают PChar(Strings[i])
> function SetPChar( var APChar: PChar; const ACopyString:
Не надо в функции распределять память.
Возьми за правило, и волосы у тебя сохранятся гораздо дольше.
--
Regards, LVT.
Ketmar (2006-10-16 20:13:00) [6]>[21] MetalFan(c) 16-Oct-2006, 20:10
> if lLenStr > 0 then inc(lLenStr);
угу. вот это-то я и забыл. %-) похмеляццо надо чаще. %-)
MetalFan (2006-10-16 20:12:00) [7]Leonid Troyanovsky © (16.10.06 20:10) [20]
вне функции имеем TList, в котором хранятся таким образом выделяемые PChar'ы...
MetalFan (2006-10-16 20:10:00) [8]а, ну да, вот что в итоге у меня получилось:
function SetPChar( var APChar: PChar; const ACopyString: string): PChar;
var
lLenStr: Integer;
begin
lLenStr := Length(aCopyString);
if lLenStr > 0 then
inc(lLenStr);
ReallocMem(aPChar, lLenStr);
if lLenStr > 0 then
Move(aCopyString[1], aPChar^, lLenStr);
result := aPChar;
end;
Leonid Troyanovsky (2006-10-16 20:10:00) [9]
> MetalFan © (16.10.06 19:04) [7]
> string в pchar, чтобы дальнейшая судьба string'а никак
> не влияла на резульирующий pchar.
Обычно в этих случаях поступают так:
Допустим, что p - указатель на буфер достаточного размера,
скажем, a: array [0..MAX_BUF] of Char
Тогда нам достаточно сделать StrPCopy(a, s).
Хотя, конечно, предпочтительней StrPLCopy.
Если такого массива нет, то для начала, распределим
буфер (StrAlloc, GetMem), как минимум Length(s)+1 байт.
Ну, а далее - StrP(L)Copy.
Когда в оной строке более нет нужды делаем StrDispose/FreeMem.
Больше, собс-но, ничего не нужно.
Хотя, конечно, вышеописанное легко сделать и с помощью Move.
Главное, что нет никакой необходимости писать некую функцию,
которая объединит распределение буфера и копирование в него,
бо от этого возникает одна лишь путаница.
--
Regards, LVT.
MetalFan (2006-10-16 20:09:00) [10]2 Ketmar © [17,18]
да ладно, ерунда)
спасибо за помощь в оптимизации кода!
Ketmar (2006-10-16 20:04:00) [11]зыж не зря я свои проекты начинаю писать только часа через 4 после того, как проснусь. %-)
Ketmar (2006-10-16 20:03:00) [12]ай. ай. ай. каюсь. посыпаю тыкву пеплом. больше не буду спросонья код давать! таки налажал. код прошу считать недействительным. %-)
MetalFan (2006-10-16 20:03:00) [13]с учетом след.изменений валиться все перестало %)
var
lLenStr: Integer;
begin
lLenStr := Length(aCopyString);
if lLenStr > 0 then
begin
ReallocMem(aPChar, lLenStr+1);
Move(aCopyString[1], aPChar^, lLenStr+1);
end
else
ReallocMem(aPChar, 0);
result := aPChar;
Palladin (2006-10-16 19:51:00) [14]
> [13] Ketmar ©
Это как? Резервируешь Length, а Move делаешь на Length+1 ? ай ай ай... :)
> всё работает.
Ага, "по встречке тоже можно ехать" (с) :)
Loginov Dmitry (2006-10-16 19:51:00) [15]Ketmar © (16.10.06 19:33) [13]
ReallocMem(aPChar, lLenStr);
Единичку к lLenStr было бы неплохо приплюсовать, имхо
Ketmar (2006-10-16 19:33:00) [16]>[12] MetalFan(c) 16-Oct-2006, 19:30
>вместо этого [0] проэкт просто "умирает" с AV сразу после
>вызова...
ищи у себя баг.
{$APPTYPE CONSOLE}
function SetPChar (var aPChar: PChar; const aCopyString: string): PChar;
var
lLenStr: Integer;
begin
lLenStr := Length(aCopyString);
ReallocMem(aPChar, lLenStr);
if lLenStr > 0 then Move(aCopyString[1], aPChar^, lLenStr+1);
result := aPChar;
end;
var
s: string;
p: PChar;
begin
p := nil; s := 'test';
SetPChar(p, s); WriteLn('"', p, '"');
s := 't1';
SetPChar(p, s); WriteLn('"', p, '"');
s := '';
SetPChar(p, s); if p > nil then WriteLn('!');
end.
всё работает.
MetalFan (2006-10-16 19:30:00) [17]с этим
> Ketmar © (16.10.06 19:09) [8]
вместо этого [0] проэкт просто "умирает" с AV сразу после вызова...
Ketmar (2006-10-16 19:13:00) [18]натурально, справедливо только для {$H+}.
Ketmar (2006-10-16 19:12:00) [19]>[9] MetalFan(c) 16-Oct-2006, 19:12
>а #0 в конце разве будет? или в string'е тоже #0 в кноце "
>висит"?
rtfm.
MetalFan (2006-10-16 19:12:00) [20]
> Ketmar © (16.10.06 19:09) [8]
а #0 в конце разве будет? или в string'е тоже #0 в кноце "висит"?