Удаление элемента дин. массива[Решено]

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Удаление элемента дин. массива[Решено]

Сообщение novo » 11.03.2012 23:46:20

Доброго времени)

Немного по бояним)
Нашел в сети вот такую штуку для удаления элементов динамического массива

Код: Выделить всё
A: array of .....

.......

Last:= high(A);
  move(A[Index+1],A[Index],(Last-Index)*sizeof(A[Index]));
  setlength(A,Last);


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

Код: Выделить всё
Ta= record
    Date: Tdate;
    Time: Ttime;
    TypeRecord: integer;
    text: string;   
    param: string   
  end;

..........

var
A: array of Ta;


Подскажите, как с этим боротся?

Заранее спасибо!!!
Последний раз редактировалось novo 13.03.2012 19:45:09, всего редактировалось 1 раз.
novo
новенький
 
Сообщения: 43
Зарегистрирован: 31.07.2011 21:35:10

Re: Удаление элемента дин. массива

Сообщение SSerge » 12.03.2012 05:56:42

novo писал(а):Подскажите, как с этим боротся?


Не работать на перекрывающихся областях памяти. Раз. :D
Внимательно прочитать описание процедуры move. Там написано, почему сие происходит.

Код: Выделить всё
  Last:= high(A);
  move(A[Index+1],A[Index],(Last-Index)*sizeof(A[Index]));
  setlength(A,Last);


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

И, я бы сказал, без особой необходимости и чёткого понимания, что вы делаете, не стоит никогда пытаться работать с внутренним двоичным представлением данных. Сделайте копирование через цикл - так хоть будет работать, если накодите правильно. И, если есть необходимость менять динамически размер массива, то для этой цели есть TList и его наследники и масса других библиотек.
SSerge
энтузиаст
 
Сообщения: 971
Зарегистрирован: 12.01.2012 05:34:14
Откуда: Барнаул

Re: Удаление элемента дин. массива

Сообщение debi12345 » 12.03.2012 08:54:08

Нижеперечисленный код работает на простых типах. Кстати, RECORD-ы пробовали объявлять PACKED ?

procedure additem(var dest: winidarty; const value: winidty);
begin
setlength(dest,high(dest)+2);
dest[high(dest)]:= value;
end;

procedure deleteitem(var dest: stringarty; index: integer);
begin
if (index < 0) or (index > high(dest)) then begin
tlist.Error(SListIndexError, Index);
end;
dest[index]:= '';
move(dest[index+1],dest[index],sizeof(dest[0])*(high(dest)-index));
pointer(dest[high(dest)]):= nil;
setlength(dest,high(dest));
end;

procedure deleteitem(var dest: msestringarty; index: integer);
begin
if (index < 0) or (index > high(dest)) then begin
tlist.Error(SListIndexError, Index);
end;
dest[index]:= '';
move(dest[index+1],dest[index],sizeof(dest[0])*(high(dest)-index));
pointer(dest[high(dest)]):= nil;
setlength(dest,high(dest));
end;

procedure deleteitem(var dest: integerarty; index: integer);
begin
if (index < 0) or (index > high(dest)) then begin
tlist.Error(SListIndexError, Index);
end;
move(dest[index+1],dest[index],sizeof(dest[0])*(high(dest)-index));
setlength(dest,high(dest));
end;

procedure deleteitem(var dest: booleanarty; index: integer);
begin
if (index < 0) or (index > high(dest)) then begin
tlist.Error(SListIndexError, Index);
end;
move(dest[index+1],dest[index],sizeof(dest[0])*(high(dest)-index));
setlength(dest,high(dest));
end;

procedure deleteitem(var dest: realarty; index: integer);
begin
if (index < 0) or (index > high(dest)) then begin
tlist.Error(SListIndexError, Index);
end;
move(dest[index+1],dest[index],sizeof(dest[0])*(high(dest)-index));
setlength(dest,high(dest));
end;

procedure deleteitem(var dest: complexarty; index: integer);
begin
if (index < 0) or (index > high(dest)) then begin
tlist.Error(SListIndexError, Index);
end;
move(dest[index+1],dest[index],sizeof(dest[0])*(high(dest)-index));
setlength(dest,high(dest));
end;

procedure deleteitem(var dest: pointerarty; index: integer);
begin
if (index < 0) or (index > high(dest)) then begin
tlist.Error(SListIndexError, Index);
end;
move(dest[index+1],dest[index],sizeof(dest[0])*(high(dest)-index));
setlength(dest,high(dest));
end;

procedure deleteitem(var dest: winidarty; index: integer);
begin
if (index < 0) or (index > high(dest)) then begin
tlist.Error(SListIndexError, Index);
end;
move(dest[index+1],dest[index],sizeof(dest[0])*(high(dest)-index));
setlength(dest,high(dest));
end;
Аватара пользователя
debi12345
долгожитель
 
Сообщения: 5761
Зарегистрирован: 10.05.2006 23:41:15
Откуда: Ташкент (Узбекистан)

Re: Удаление элемента дин. массива

Сообщение stikriz » 12.03.2012 09:34:29

Замените в структуре типы строк на короткие, например string[200] или сколько там надо.
Аватара пользователя
stikriz
энтузиаст
 
Сообщения: 612
Зарегистрирован: 15.03.2006 09:37:47

Re: Удаление элемента дин. массива

Сообщение qivi » 13.03.2012 14:40:28

А я перебираю массив в цикле, переписывая его в другой "сервисный" массив, естественно кроме удаляемого элемента. Ничего не теряется даже если в рекорде объявлен ещё массив, вроде и на скорость не жалуюсь (хотя ещё не довелось потестить на действительно крупных массивах). Это сильно кривой подход?
Аватара пользователя
qivi
энтузиаст
 
Сообщения: 703
Зарегистрирован: 19.01.2009 13:45:54
Откуда: Россия

Re: Удаление элемента дин. массива

Сообщение zub » 13.03.2012 16:11:06

Код из первого поста кроме потери стрингов в A[last-1] массива содержит еще и утечку стрингов из A[Index] - стираемый элемент не финализируется.
По идее должно быть чтото наподобии:
Код: Выделить всё
A: array of ta
temp:ta
.......
Last:= high(A);
temp:=A[Index];
move(A[Index+1],A[Index],(Last-Index)*sizeof(ta));
fillchar(a[last],0,sizeof(ta));
a[last]:=temp;
setlength(A,Last-1);
zub
долгожитель
 
Сообщения: 2887
Зарегистрирован: 14.11.2005 23:51:26

Re: Удаление элемента дин. массива

Сообщение svk12 » 13.03.2012 17:16:16

А не проще ли использовать TList?
svk12
постоялец
 
Сообщения: 409
Зарегистрирован: 09.06.2008 18:42:47

Re: Удаление элемента дин. массива[Решено]

Сообщение novo » 13.03.2012 19:46:53

Использовал копирование через цикл

Спасибо всем :wink:
novo
новенький
 
Сообщения: 43
Зарегистрирован: 31.07.2011 21:35:10


Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: Google [Bot] и гости: 240

Рейтинг@Mail.ru