Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > Длина строки


Автор: Dmitry_177 20.5.2007, 00:13
При использовании API функций часто бывает пользуются такой схемой:

Код

var
str: string;
...

SetLength(str, MAX_PATH);
...какаянибудь API функция в которую передается PChar(str)
str := PChar(str);  или SetLength(str, StrLen(PChar(str)));


Так вот я хотел бы спросить, как потом правильней будет укоротить спроку, так:

Код

str := PChar(str);


или так:

Код

SetLength(str, StrLen(PChar(str)));



И еще, потом после использования переменной str, т.е. когда она стала ненужной, нужно ли ей задавать нулевой размер, т.е так:

Код

SetLength(str, 0);


чтобы в памяти она не занимала места?

Автор: Poseidon 20.5.2007, 02:38
Цитата(Dmitry_177 @  20.5.2007,  00:13 Найти цитируемый пост)
И еще, потом после использования переменной str, т.е. когда она стала ненужной, нужно ли ей задавать нулевой размер
Нет. Переменная str занимает место сразу после обявления (var), т.к. она string. И даже если "длина" переменной будет равна 0, она все-равно будет занимать место в памяти.
Высвободится память сразу после выполнения функции или процедуры, в каторой обьявлена переменная.

Цитата(Dmitry_177 @  20.5.2007,  00:13 Найти цитируемый пост)
Так вот я хотел бы спросить, как потом правильней будет укоротить спроку
Правильнее будет SetLength(str, StrLen(PChar(str))); т.к. конвертирование форматов для форматирования данных - не лучший вариант.

Автор: Dmitry_177 20.5.2007, 07:49
А если будет такая схема:

Код

SetLength(str, MAX_PATH);
...какаянибудь API функция в которую передается PChar(str)
SetLength(str, StrLen(PChar(str)));


а потом в этой же функции или процедуре нужно str присвоить какую-нибудь строку

str := 'vbrftgbtrbrtntrentrnrthne';

так вот если присваемая строка будет длиннее чем мы задали SetLength-ем, она обрежется? ИМХО вообще наверно переполнение будет.. Как сделать из str опять обычный string?

Автор: MetalFan 20.5.2007, 11:01
чаще всего функции WinApi возвращают длину возвращаемой строки...

Автор: Snowy 20.5.2007, 11:17
Цитата(Dmitry_177 @  20.5.2007,  00:13 Найти цитируемый пост)
ак вот я хотел бы спросить, как потом правильней будет укоротить спроку, так:
str := PChar(str);
или так:
SetLength(str, StrLen(PChar(str)));
str := PChar(str);
Второе просто производит больше ненужных действий.

Цитата(Dmitry_177 @  20.5.2007,  00:13 Найти цитируемый пост)
И еще, потом после использования переменной str, т.е. когда она стала ненужной, нужно ли ей задавать нулевой размер, т.е так:
SetLength(str, 0);
чтобы в памяти она не занимала места?
Нет не нужно.
При выходе за пределы видимости вся память, занимаемая строкой, будет освобождена автоматически.

Цитата(Dmitry_177 @  20.5.2007,  07:49 Найти цитируемый пост)
а потом в этой же функции или процедуре нужно str присвоить какую-нибудь строкуstr := 'vbrftgbtrbrtntrentrnrthne';так вот если присваемая строка будет длиннее чем мы задали SetLength-ем, она обрежется?
Строка автоматически изменит свой размер.
При прямом присвоении уже не имеет значения, что там ей раньше присваивалось и какой размер устанавливался.

Автор: Alexeis 20.5.2007, 12:03
Dmitry_177, передавать в API лучше всего строку типа 
  str : array[0..size] of char; с нулем на конце.

При конвертировании String в PChar нарушается работа подсчета ссылок в строках типа String. В результате легко испортить данные по выходу из процедуры. 

Если размер строки неизвестен, то можно воспользоваться следующим способом.
Код

procedure TForm1.FormCreate(Sender: TObject);
type
  longstr   = array[0..High(Integer) - 1] of char;
  plongstr = ^longstr;

var
  myStr : plongstr;
  strlen : DWORD;
  s    : String;
begin
   s := 'text' + ' что-то еще' + ' и еще что-то';

   strlen := Length(s) + 1;
   GetMem(myStr, strlen);
   move(s[1], myStr^, strlen);
   SetWindowText(Form1.Handle, PChar(myStr));
...


  Каждый остается со своей строкой. Делфийская прога с делфийской, а винда с сишной строкой. Только прийдеться уже вручную освобождать память строки myStr, тогда  когда она уже будет не нужна.

Автор: Dmitry_177 21.5.2007, 09:44
У меня еще вопрос.. делаем мы так:

Код

SetLength(str, MAX_PATH);
...какаянибудь API функция в которую передается PChar(str), а длинну строки MAX_PATH или MAX_PATH + 1?


ведь строка же должна завержаться нулевым символом, а это значит еще один символ.. Так вот чтобы правильно все было сколько нужно задать в SetLength и в какойнибудь API на примере с MAX_PATH?

Автор: Alexeis 21.5.2007, 09:56
Dmitry_177, ansi строки всегда завершаются нулем. Это делает компилятор за нас. Потому они совместимы с PChar.

Автор: Dmitry_177 21.5.2007, 11:41
Я это почему спросил вообще, чтобы избежать переполнения буфера, т.е. чтобы не записывался нуль за пределом MAX_PATH..

Автор: Dmitry_177 21.5.2007, 14:45
Я где-то слышал что, когда выполняется SetLength(str, MAX_PATH), для str резервируется MAX_PATH+1 байт. Лишний байт - это как раз для нулевого символа в конце, который при обычной работе со stringом добавляется автоматически.. Правда ли это?

Автор: Alexeis 21.5.2007, 14:54
Цитата(Alexeis @  21.5.2007,  09:56 Найти цитируемый пост)
ansi строки всегда завершаются нулем. Это делает компилятор за нас. 


Автор: Dmitry_177 21.5.2007, 15:17
Alexeis, да, но если задаем размер строки MAX_PATH символов, и API функция передаст в нее ровно MAX_PATH символов.. получится так что нулевой символ туда уже не запишется.. Вот я и спрашиваю нужноли MAX_PATH +1 делать? И еще: Я где-то слышал что, когда выполняется SetLength(str, MAX_PATH), для str резервируется MAX_PATH+1 байт. Лишний байт - это как раз для нулевого символа в конце, который при обычной работе со stringом добавляется автоматически.. Правда ли это?

Автор: Alexeis 21.5.2007, 15:22
Dmitry_177, для строки резервируется length(s) + 9 байт, 4 для счетчика ссылок 4 для длинны и 1 для завершающего нуля.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)