Добрый день всем) интересует такой момент, не могу его понять. Вот я сдвигаю массив процедурой Move, затем уменьшаю длину массива SetLength у меня всё нормально уменьшается как надо, вот только почему-то последний элемент массива после уменьшения его длины просто обнуляется. WTF? Code: Acc := AccArr[0, 0]; Pass := AccArr[0, 1]; Finalize(AccArr[0, 0]); Finalize(AccArr[0, 1]); // Делаем сдвиг массива влево на 1 Move(AccArr[1], AccArr[0], (Length(AccArr) - 1)*SizeOf(AccArr)); // Уменьшаем длину массива SetLength(AccArr, Length(AccArr) - 1);
Голова не варит сегодня, но могу скачать точно что есть ошибка с SizeOf(AccArr), это не правильно, т.к. AccArr - ссылка на динамический массив, и размер равен 4 байтам. Ты копируешь ячейки данного массива и если размер ячейки не равен 4, то будут проблемы. Если ячейка массива - еще один динамический массив или структура содержащая динамические строки, то копировать придется его в ручную, если нет - то делаем так: Code: Acc := AccArr[0, 0]; Pass := AccArr[0, 1]; Finalize(AccArr[0, 0]); Finalize(AccArr[0, 1]); // Делаем сдвиг массива влево на 1 Move(AccArr[1], AccArr[0], High(AccArr)*SizeOf(AccArr[0])); // Уменьшаем длину массива SetLength(AccArr, High(AccArr));
У меня динамические строки подгружаемые из файла(( ну а в ручную только последний элемент или весь массив? и как понять в ручную? есть еще вариант последнюю ячейку массива держать пустой, вроде работает. ну это бред мне кажется, хотя лучше чем копировать на мой взгляд...
В ручную я имел ввиду : Code: {Сдвиг} for i := n to High(AccArr) - 1 do Begin SetLength(AccArr[i], High(AccArr[i+1])+1); for j := 0 to High(AccArr[i]) do AccArr[i, j] := AccArr[i+1, j]; end; {Удаление последнего} SetLength(AccArr, High(AccArr)); n - индек элемента, который нужно удалить.
Понятно, просто, если подгрузят 50 тысяч акков то боюсь будет худо) У меня вот всё норм работает если я создаю последний элемент массива пустые строки.... тогда всё сдвигается и удаляется вроде бы как надо. С помощью Move.
код TList<T> Code: procedure TList<T>.DoDelete(Index: Integer; Notification: TCollectionNotification); var oldItem: T; begin if (Index < 0) or (Index >= Count) then raise EArgumentOutOfRangeException.CreateRes(@SArgumentOutOfRange); oldItem := FItems[Index]; FItems[Index] := Default(T); //это Dec(FCount); if Index <> Count then begin System.Move(FItems[Index + 1], FItems[Index], (Count - Index) * SizeOf(T)); FillChar(FItems[Count], SizeOf(T), 0); // и это обезательно! (не помню зачем) end; Notify(oldItem, Notification); end; И вообще: советую перейти на Delphi XE2 и TList<T> вместо масивов. А если нужна очередь - тогда TQueue<T>.
Code: // Делаем сдвиг массива влево на 1 Move(AccArr[1], AccArr[0], (Length(AccArr) - 1)*SizeOf(AccArr)); // Уменьшаем длину массива SetLength(AccArr, Length(AccArr) - 1); ясно же - память изначалаьно не зарезевирована под массив. ошибочный код, без задания параметров массива с учётом переноса в другой, временный. правильно - задать величину оригинального массива и временный, для операций копирования данных.