Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Очистить массив из Integer-ов [D7, WinXP]


Dmitry_177 ©   (2007-03-30 09:22:00) 

есть массив из Integer-ов.. Мне его надо очистить, делаю FillChar, чтобы заполнить его нулями.. И почему-то после этого если како-му то его элементу что-то присвоить, то будет ошибка AV. Вот так выскакивает AV:

var
 Codes: array of Integer;

procedure TForm1.Button1Click(Sender: TObject);
begin
 SetLength(Codes, 1);
 FillChar(Codes, SizeOf(Codes), 0);
 Codes[0] := 212;
 MessageBox(0, PChar(IntToStr(Codes[0])), '', 0);
end;

На строке Codes[0] := 212;

Подскажите пожалуста почему так?


MsGuns   (2007-04-02 23:16:00) [1]

Буря в стакане блин, - прав Кетмарь, метлы нужны


Dmitry_177   (2007-04-02 23:05:00) [2]

да, но этот ИМХО быстрей..


Asail   (2007-04-02 20:47:00) [3]


> VEZ   (02.04.07 17:54) [12]

> Имхо так

Ну, я и говорю - смещением...


> Dmitry_177   (02.04.07 18:55) [13]
> Мне тут подсказали еще лучше способ =)


Чем лучший и по сравнению с каким? Тот-же способ, что у VEZ.


Dmitry_177   (2007-04-02 18:55:00) [4]

Мне тут подсказали еще лучше способ =)

//удалить i-й элемент массива

move(codes[i+1],codes[i],(length(codes)-i-1)*sizeof(integer));
setlength(codes,length(codes)-1);


VEZ   (2007-04-02 17:54:00) [5]


> А как можно из такого массива удалить какойнибудь элемент?
>  Например будет он состоять из 5 элементов, а удалить к
> примеру 3?


Имхо так

procedure TForm2.Button1Click(Sender: TObject);
var
 a: array of Word;
 i: Integer;
begin
 SetLength(a, 5);
 Label1.Caption:= '';
 Label2.Caption:= '';
 for i := 0 to Length(a) - 1 do
 begin
   a[i]:= i;
   Label1.Caption:= Label1.Caption + IntToStr(a[i]) + ' ';
 end;
 // Remove 3th element
 MoveMemory(@a[3], @a[4], (Length(a)-3) * SizeOf(Word));
 SetLength(a, 5-1);
 // element has removed
 for i := 0 to Length(a) - 1 do
   Label2.Caption:= Label2.Caption + IntToStr(a[i]) + ' ';
end;


Asail   (2007-04-02 11:33:00) [6]

ИМХО Никак.
Только смещением (т.е. 4-й в 3-й и 5-й в 4-й и т.д., потом SetLength(n-1))


Dmitry_177   (2007-04-02 11:17:00) [7]

А как можно из такого массива удалить какойнибудь элемент? Например будет он состоять из 5 элементов, а удалить к примеру 3?


Loginov Dmitry   (2007-03-30 18:58:00) [8]

> Мы ведиляем под массив память: SetLength(Codes, 1); а когда
> массив уже становится ненужным нужно ли освобождать память,
> которая была под него выделена?


Как хочешь. Можешь освобождать, а можешь и не освобожать. Для освобождения памяти следует сделать следующее:
Code := nil;


SergGG   (2007-03-30 15:01:00) [9]

> SetLength(Codes, 1) .... FreeMem(Codes); ???
Их нельзя связать.
См. [5]. Там нет SetLength


Dmitry_177   (2007-03-30 14:42:00) [10]

Мы ведиляем под массив память: SetLength(Codes, 1); а когда массив уже становится ненужным нужно ли освобождать память, которая была под него выделена? Как-нибудь так: FreeMem(Codes); ???


Ketmar   (2007-03-30 12:21:00) [11]

на кол. что, справку отменили? там по dynamic arrays весьма немало текста... кажыдцо, пора опять мётлы раздавать... %-((


SergGG   (2007-03-30 09:47:00) [12]

> Dmitry_177   (30.03.07 09:22)
Если тебе нужно использовать FillChar...

Type
TCodes= Integer;
PCodes=^TCodes;

procedure TForm1.Button1Click(Sender: TObject);
var Codes:PCodes;
begin
GetMem(Codes, SizeOf(TCodes));
FillChar(Codes^, SizeOf(Codes), 0);
Codes^ := 212;
MessageBox(0, PChar(IntToStr(Codes^)), '', 0);
FreeMem(Codes, SizeOf(TCodes));
end;


Dmitry_177   (2007-03-30 09:40:00) [13]


> зачем тут обнулять, если выделяешь 1 элемент и тут же его
> записываешь

Это я к примеру же привел.. А мне надо к примеру выделить 100 элементов, и какие-то из них заполнить, а остальные что были нулями.. Вот я и подумал о том, что если выделить 100 элементов SetLength-ем, как бы там мусора небыло, чтобы не оказалось что какой-то элемент уже чему-то равен, вот и решил обнулять..


begin...end   (2007-03-30 09:37:00) [14]

Потому что переменная, имеющая тип "динамический массив", по сути является указателем на тело массива, т.е. содержит адрес его первого (нулевого) элемента. Следовательно, в строке с FillChar Вы записываете нули не в тело массива, а в указатель на него. В результате ссылка портится -- теперь вместо реального адреса тела массива она содержит ноль. Поэтому дальнейшая попытка записи в массив с использованием этой ссылки приводит к AV -- ведь фактически Вы пытаетесь записать что-то по нулевому адресу, а чтение и запись из памяти / в память по такому адресу запрещены.

Чтобы правильно очистить такой массив, нужно строку с FillChar переписать так: FillChar(Codes[0], sizeof(Codes[0]) * Length(Codes), 0).

Однако, если речь идёт об очистке массива array of integer, только что инициализированного первым вызовом SetLength (как в приведённом примере), то это лишнее -- все элементы такого нового массива вначале содержат ноль.


TRUNK   (2007-03-30 09:32:00) [15]


> Dmitry_177   (30.03.07 09:22)
> Подскажите пожалуста почему так?

Потому что массив динамический, и Codes на самом деле содержит указатель на массив. Поэтому FillChar обнуляет указатель, что равноценно Codes := nil, поэтому и последующее обращение к массиву вызывает AV.


ЮЮ   (2007-03-30 09:29:00) [16]

FillChar(Codes, SizeOf(Codes), 0);
зачем тут обнулять, если выделяешь 1 элемент и тут же его записываешь

SizeOf(Codes) не имеет никакого отношения к размеру памяти, занятой Codes, это указатель на область памяти. По этой же причине, нельзя указывать Codes первым параметром, надо Codes[0];

Имхо, достаточно
Codes := nil;
перед новым наращиванием массива
SetLength(Codes, 1);


Наверх

Титульная страница Поиск, карта сайта Написать письмо