![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Динамические массивы
DeadMeat © (2008-11-21 13:58:00)Здравсте.
Есть вопрос по поводу динамических массивов.
Представим, что у нас есть два динамических массива, такого вида:
A1: array of byte;
A2: array of single;
Задача состоит в том, чтобы передав их в определенную процедуру, изменить их длинну и "вернуть назад".
Т.е. нужна некая процедура, которая принимает на вход динамические массивы любого типа, либо поинтер на них, либо еще что. Результатом ее действия должен быть увеличенный на N элементов (или байт, если по другому не получится) переданный ранее массив.
Нечто вроде:
procedure Reallocate(....; const ElementSize: integer);
begin
.... // увеличение длинны массива на ElementSize
end;
Если я правильно понял, то передать любой массив можно через Open Arrays, но по поводу них справка четко говорит, что менять его длинну в процедуре нельзя.
Пробовал передать просто поинтер, выделить в нем память (GetMem) размером с ElementSize байтов, скопировать в новое место данные из старого (типа того, что делает SetLength) и вернуть новый поинтер на место первого, но память выделяется не понятно как. Т.е. смотрю в дебагер после этих действий и вижу, что на месте этого массива получился всякий мусор. Не в том смысле, что там данные "левые", а в том, что.... Даже не знаю как объяснить. Ну допустим я выделил (точнее хотел выделить) 10 элементов, каждый по 720 байт (нечто типа array of TMyRecord, размер которого 720 байт). В результате в дебагере вижу, что первые два элемента выделились, другие два - нет и т.п. "фигня".
Вообщем суть вопроса. Как сделать так, чтобы в процедуру можно было передать динамический массив любого типа, изменить его размер и "вернуть назад", т.е. чтобы по выходу из этой процедуры, этим массивом можно было пользоваться, записывая данные в его "новые" места.
Германн (2008-11-23 04:39:00) [1]
> в каждую вторую ветку вставлять? а то и чаще.
В каждую первую!. :)
Ну нужно иметь под рукой что-то "художественное" для ответов.
Твой пример второй. Первый "художественный" ответ был дан ЮЗ. Его я то же бы попросил бы опубликовать где-то на данном форуме. Это ответ "телефонная книжка".
Где именно? Ну у нас на форуме есть две "скрытые" конференции. Плюс "новая" версия форума.
sniknik (2008-11-23 02:06:00) [2]> Повторить твой незабываемый пример с "переходом дороги для покупки хлеба" не хочешь?
в каждую вторую ветку вставлять? а то и чаще. имхо большинство тут не видят разницы между задачей и методом решения.
Германн (2008-11-23 01:05:00) [3]
> sniknik © (22.11.08 11:18) [33]
Повторить твой незабываемый пример с "переходом дороги для покупки хлеба" не хочешь?
> Задача состоит в том, чтобы передав их в определенную процедуру,
> изменить их длинну и "вернуть назад".
>
:)
P,S. <offtop>
Можно пойти по пути Palladin.
</offtop>
P.P.S. Вот очень желательно иметь под рукой нечто, чтобы объяснить автору отличие "технического вопроса" от "описания задачи".
Amoeba (2008-11-23 00:17:00) [4]
> DeadMeat (22.11.08 11:44) [34]
>
> Мда.. По всей видимости мы друг-друга не понимаем. Ну и
> ладно...
> Всем спасибо за помощь.
Все еще чешется ... Ну и Господь с тобой.
DeadMeat (2008-11-22 11:44:00) [5]Мда.. По всей видимости мы друг-друга не понимаем. Ну и ладно...
Всем спасибо за помощь.
sniknik (2008-11-22 11:18:00) [6]> Может таки есть способ
а [27] разве не способ?
DeadMeat (2008-11-22 10:27:00) [7]
> Amoeba © (22.11.08 00:51) [31]
Ну тогда мне совершенно не понятны [1], [2] и [14]
Может таки есть способ, раз люди о нем намекнули.. По крайней мере мне так показалось, что намекнули..
Amoeba (2008-11-22 00:51:00) [8]
> Как можно используя SetLength реализовать [0] ?
Все еще Гондурас чешется?
DeadMeat (2008-11-21 21:24:00) [9]
> Сергей М. © (21.11.08 21:19) [28]
Ну собсна да... хоца знать все новое. ))
DeadMeat (2008-11-21 21:23:00) [10]
> Sapersky (21.11.08 21:12) [27]
Ну это почти то, что делал я. Разница конечно есть, но смысл тот же. Каст и ресайз.
Вопрос именно в том, есть ли чуток более стандартный способ.. Просто посты из [1], [2] и [14] наталкивают меня именно на эту мысль.. Что я чтото упустил из стандартного... может синтаксис какой не знаю..
Сергей М. (2008-11-21 21:19:00) [11]
> Как можно используя SetLength реализовать [0] ?
Т.е. это самое что ни на есть принципиальное ослиное ничем не аргументированное упрямство ?)
Sapersky (2008-11-21 21:12:00) [12]// Arr is Delphi dymamic array (array of ...)
// array elements MUST NOT contain elements with automatic memory management,
// i.e. long strings, variants etc.
// this proc may not work in future Delphi versions
// (if dymamic array format will change)
procedure Mem_GrowArray(Var Arr; NewCount, ElSize : Integer);
Type
TByteArr = array of Byte;
Var
Capacity : Integer;
PLength : PInteger;
begin
PLength := PInteger(Arr);
If (PLength <> nil) then begin
Dec(PLength);
If (NewCount <= PLength^) then Exit; // we fit to existing capacity, no need to grow
Capacity := PLength^ * 2;
If Capacity < NewCount then Capacity := NewCount;
PLength^ := PLength^ * ElSize;
// as we cast array to byte array, we need to temporarily convert
// its length in bytes for correct reallocation
end else
Capacity := NewCount; // was no array - just allocate NewCount elements
SetLength(TByteArr(Arr), Capacity * ElSize);
If (Capacity > 0) then begin
PLength := PInteger(Arr); Dec(PLength);
PLength^ := Capacity; // set length in elements
end;
end;
DeadMeat (2008-11-21 20:42:00) [13]
> Сергей М. © (21.11.08 19:30) [25]
Хех... Ну про удобства уже сказали чуть выше. В принципе я согласен. Для меня както динамические массивы удобней остальных методов. А теперь практически совсем удобны. Осталась пара нюансов, но уже не таких существенных.
Однаков все-же один вопрос для меня остался не открытым. Как можно используя SetLength реализовать [0] ?
Сергей М. (2008-11-21 19:30:00) [14]
> всякие "вспомогательные" классы, типа TList не подходят
Понятно - Коран запрещает.
> Просто выделять память через GetMem ?
Почему бы и нет ?
> Но мне надо обращаться к этим элементам, которые будут записаны.
> . Мне их надо читать, обрабатывать и т.п.
Да на здоровье !
Коран же не запрещает)..
И Делфи тоже, кстати.
Sapersky (2008-11-21 19:26:00) [15]Может, речь идёт о конструкциях вроде:
Type
PByteArr = ^TByteArr;
TByteArr = array [0..0] of Byte;
Var
Arr : PByteArr;
Память выделяется через GetMem/FreeMem, можно обращаться к элементам по индексу.
Но фактически это менее удобно чем дин. массивы:
1) Содержимое при отладке не видно;
2) Автоматически не уничтожается;
3) Непонятно что делать при наличии в массиве managed-типов, скорее всего, придётся инициализировать/прибивать вручную.
Одна радость - скомпилируется в D1-3 и вроде даже в TP :)
А, нет, есть одно достоинство - позволяет делать двумерные массивы, лежащие в памяти "одним куском". Ну или обращаться к произвольному блоку памяти как к двумерному массиву (картинке, например).
Многомерные дин. массивы представляют собой массивы указателей, реальные данные начинаются только в последнем измерении. Это не всегда удобно и несколько замедляет доступ к элементу.
DeadMeat (2008-11-21 18:49:00) [16]
> Сергей М. © (21.11.08 18:07) [22]
О_о
Тогда о чем? При условии использования только "своего". В том смысле, что всякие "вспомогательные" классы, типа TList не подходят.
Просто выделять память через GetMem ? Но мне надо обращаться к этим элементам, которые будут записаны.. Мне их надо читать, обрабатывать и т.п.
Я в замешательстве...
Сергей М. (2008-11-21 18:07:00) [17]
> DeadMeat (21.11.08 17:27) [21]
> юзать для этого статические массивы
Ктосказал про статику ?
Ни о какой статике не идет и речи ..
DeadMeat (2008-11-21 17:27:00) [18]
> Сергей М. © (21.11.08 17:03) [20]
Ну... отказаться не могу. Размер данных я заранее не знаю... юзать для этого статические массивы со своими счетчиками будет расточительно, т.к. размеры данных будут не маленькими.
А передевать.... есть такое у меня желание. Не создавать свой класс для списков, а использовать везде обычные массивы, но для наращивания вызывать одну функцию, которая будет делать это с запасом.
Отлично понимаю, что сделать свой класс будет на много удобно, но условия у меня чуто специфичные.
Сергей М. (2008-11-21 17:03:00) [19]
> хотелось получить решение, удобное в использовании
Откажись от дин.массивов вообще- будет чуть менее удобно, но зато универсально.
Да и вообще не оч понятно, за каким лешим нужно передавать куда-то дин. массив (да и не только динамический), тольколишь для того чтобы увеличить его размерность.. Почему это нелья сделать прямо в вызывающем коде ?
DeadMeat (2008-11-21 16:55:00) [20]
> Sapersky (21.11.08 16:17) [16]
Ну это все понятно. Я это и затеял для того, чтобы сделай некое подобие TList у себя. Как раз для наращиваний массивов не по одному. И тему ту читал..
> Сергей М. © (21.11.08 16:22) [17]
Эмм... да вот хотелось получить решение, удобное в использовании. Вот и кастил туда-сюда типы. Но то, чего я хотел, не получилось... Будем юзать то, что показал мне товарищ Sapersky.