Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2003.06.09;
Скачать: CL | DM;

Вниз

Когда нужно исспользовать SetLength для строк?   Найти похожие ветки 

 
MegaVolt ©   (2003-05-29 15:05) [0]

Sabj:
Для примера

for i:=1 to x do s:+s+"a";

нужно ли тут применять SetLength rf;lsq раз при увеличении s если x неизвесно (например в цикле While)? Или если s элемент динамически созданной записи?
Т.е. когда нужно когда не нужно и почему.
Заранее благодарен.


 
Skier ©   (2003-05-29 15:15) [1]

Для твоего случая - не нужно.


 
Digitman ©   (2003-05-29 15:15) [2]

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


 
Sha ©   (2003-05-29 15:19) [3]

Надо только перед обращением к символу строки по индексу, и только в том случае, если индекс превышает длину.
По окончании работы со строкой можно освободить память, устанавливаяя нулевую длину строки.


 
MegaVolt ©   (2003-05-29 15:25) [4]

Те если вот это правильно:

s:="asd";
SetLength(s,4);
s[4]="f";


Dj всех остальных случаях SetLength не применяется???


 
Skier ©   (2003-05-29 15:28) [5]

>MegaVolt © (29.05.03 15:25)
Не думаю что есть точный рецепт применения SetLength.
Всё зависит от конкретного случая...


 
Sha ©   (2003-05-29 15:30) [6]

Да


 
Digitman ©   (2003-05-29 15:33) [7]


> MegaVolt © (29.05.03 15:25)


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

если же не предпринять ни этого ни какого либо иного варианта увеличения буфера, есть ненулевой риск получить AV-исключение.


 
Sha ©   (2003-05-29 15:34) [8]

Правда, иногда еще укорачивают строку при помощи SetLength, если хвост больше не нужен.


 
MegaVolt ©   (2003-05-29 15:37) [9]

А как мне догадыватся что в этом случае нужно а тут не нужно


 
Palladin ©   (2003-05-29 15:43) [10]

Головой


 
Sha ©   (2003-05-29 15:44) [11]

Сам должен думать, что тебе надо по твоему алгоритму.
Если "Volt" больше не нужен, то: s:="MegaVolt"; SetLength(s,4);
Когда будешь пользоваться чем-нибудь, изменяющим отдельные символы внутри строки, типа FillChar или Move, действуй аналогично присваиванию s:="f";


 
Serginio   (2003-05-29 15:44) [12]

Обычно SetLength для строк используется вместо буфера (array[0..lenbuf-1]) при применении процедуры Move., но есть еще множество вариантов. При объединении строк Delphi автоматически выделит нужную память.


 
Sha ©   (2003-05-29 15:45) [13]

Поправка s[i]:="f";


 
Sandman25 ©   (2003-05-29 15:47) [14]

2MegaVolt
см Sha © (29.05.03 15:19)

Например.
SetLength(S, 15);
for i := 1 to 15 do
S[i] := chr(i+ord("A"));


 
Digitman ©   (2003-05-29 15:50) [15]


> Palladin © (29.05.03 15:43)


)))

В форуме далеко не редки ситуации, когда для целей "догадывания" используются другие, альтернативные места)


> MegaVolt


а не надо догадываться !
просто надо представлять в каждый момент времени, что происходит со строкой ПЕРЕД операцией над ней и каково будет ее состояние ПОСЛЕ той или иной операции, которая, несмотря на внутреннюю схожесть, выглядеть с т.з. Паскаль-текста может по-разному ... и при неуверенности сразу же "лезть" в исходники System и SysUtils


 
MegaVolt ©   (2003-05-29 15:56) [16]

А если я применяю такую запись

S:=copy(s,x,y);

то не нужно как я понимаю? Или всё таки нужно если размер результирующей строки меньше исходной?


 
Skier ©   (2003-05-29 15:58) [17]

>MegaVolt © (29.05.03 15:56)

F1. Читаем...

If Index is larger than the length of S, Copy returns an empty string or array.


 
Digitman ©   (2003-05-29 16:06) [18]


> MegaVolt (29.05.03 15:56)


нет, не нужно.

простейшее объяснение - никаких явных преобразований типов между результирующим типом (ф-ция возвращает string) и типом переменной s: string перед присвоением не требуется и не происходит, поэтому компилятор самостоятельно заботится о :

- перераспределении памяти под переменную s, чтобы размер ее буфера соответствовал размеру буфера строки, возвращаемой из ф-ции;

- копировании из буфера возвращаемой строки в буфер переменной s;

- уничтожении результирующей строки с автоматическим освобождением памяти под ее буфер;


 
MegaVolt ©   (2003-05-29 16:12) [19]

Я не про индех больше длинны строки а про то :

s:="MegaVolt";
s:=Copy(s,1,4);

в результате строка результата стала меньше изначальной строки вот я и спрашиваю нужно самому уменьшать строку под размер новой или дельфи сам? И кстати исходников функции Copy нету в System и SysUtils :(


 
Palladin ©   (2003-05-29 16:16) [20]

стала


 
Palladin ©   (2003-05-29 16:19) [21]

и вообще я не понимаю, не ужели трудно поэкспериментировать?
есть такая функция Length мог бы и посмотреть сам


 
Digitman ©   (2003-05-29 16:23) [22]


> исходников функции Copy нету в System и SysUtils :(


есть) ... procedure _Copy(...) смотри.

но setlength() ты там не увидишь, в ее теле, ибо этот вызов компилятор вставляет неявно


 
Skier ©   (2003-05-29 16:26) [23]


> но setlength() ты там не увидишь, в ее теле, ибо этот вызов
> компилятор вставляет неявно

А если включить Use debug DCUs ? Можно кое-что увидеть, и даже
очень интересного, особенно если прогнать построчно...:)


 
Verg ©   (2003-05-29 17:05) [24]

Например, ты принял из какой-нибудь функции (напр, из dll) буфер buff типа pchar и количество символов в нем хранящихся charcount. Задача - сделать из нее строку (string) S.

Вариант1:
S:="";
while charcount>0 do
begin
S:=S+buffer^;
inc(buffer);
dec(charcount);
end;


Вариант2:
SetLength(S, charcount);
move(buffer^, s[1], charcount);


Угадай с трех раз - какой из вариантов будет работать быстрее и занимать меньше кода?


 
MegaVolt ©   (2003-05-29 17:48) [25]

Второй вариант раз в 6 быстрее :) Начинаю понимать.

Спасибо :)


 
MegaVolt ©   (2003-05-29 17:54) [26]

Кстати вместо второго варианта можно написать? Или нет?

s:=PChar(buffer);


 
Skier ©   (2003-05-29 17:56) [27]

>MegaVolt © (29.05.03 17:54)
Можно, но зачем ? Buffer и есть PChar.


 
Serginio   (2003-05-29 18:05) [28]

2(MegaVolt) Вот и можешь получить другую строку намного большую пока не найдется #0. PCHAR можно использовать и всесто Pointer для более простой арифметики над указателями. Надо быть уверенным при ее использовании, что это указатель на нуль терминированную строку. Простой пример при использовании со стримами.
Str.Read(TypeVal,SizoOf(TypeVal));
If TypeVal=IdStroka Then
Begin
Str.Read(LenStr,SizoOf(LenStr));
SetLength(str,lenStr);
Str.Read(str[1],LenStr);
end;


 
panov ©   (2003-05-30 02:22) [29]

SetLength как раз можно использовать для ускорения работы со строками в такоом случае:

1.
var
s: String;
i: Integer;
begin
s := "";
for i := 0 to 255 do
begin
s := s + Chr(i);
end;
end;

2.
var
s: String;
i: Integer;
begin
SetLength(s,256);
for i := 0 to 255 do
begin
s[i] := Chr(i);
end;
end;


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


 
Skier ©   (2003-05-30 08:24) [30]

>panov © (30.05.03 02:22)
for i := 1 to 256 do


 
MegaVolt ©   (2003-05-30 09:54) [31]

Я имел в виду

s:=String(Buffer);

:)


 
Anatoly Podgoretsky ©   (2003-05-30 09:58) [32]

MegaVolt © (30.05.03 09:54)

s := Buffer;



 
MegaVolt ©   (2003-05-30 10:32) [33]

И это правильно???


 
Anatoly Podgoretsky ©   (2003-05-30 11:09) [34]

Конечно
S - string
buffer - PChar



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

Текущий архив: 2003.06.09;
Скачать: CL | DM;

Наверх




Память: 0.55 MB
Время: 0.021 c
1-26460
Yanis
2003-05-28 21:34
2003.06.09
Вопрос: Как убить процесс?


1-26576
Ольга
2003-05-27 13:54
2003.06.09
try ... except


1-26585
Rise
2003-05-28 14:27
2003.06.09
StringGrid


3-26346
AlexAvz
2003-05-20 13:47
2003.06.09
Работа с таблицами PARADOX


3-26365
Roka
2003-05-19 22:59
2003.06.09
DBGrid и фильтры