Использование Length() с многомерными динамическими массивами в Delphi

Я использую многомерный динамический массив в delphi и пытаюсь понять это:

У меня есть 2 отдельных значения для первого индекса и второго индекса, которые полностью разделены друг с другом.

При появлении новых значений я хочу вырастить массив, если это новое значение находится за пределами любой границы.

Для новых значений x, y

Я проверяю:

if Length(List) < (x + 1) then
 SetLength(List, x + 1);
if Length(List[0]) < (y + 1) then
 SetLength(List, Length(List), y + 1);

Это правильный способ сделать это или есть лучший способ для расширения массива по мере необходимости?

3 ответа

Я думаю, вы забыли использовать второй индекс во втором измерении;

Ваш код должен, вероятно, выглядеть следующим образом:

if Length(List) < (x + 1) then
 SetLength(List, x + 1);
if Length(List[x]) < (y + 1) then
 SetLength(List[x], y + 1);

Обратите внимание на использование "x" в качестве первого индекса измерения при увеличении второго измерения.

Одно предупреждение:

Вы должны знать о том, что Delphi также использует подсчет ссылок на динамических массивах (точно так же, как это делается с AnsiString). Из-за этого растущий массив, как и выше, будет работать, но любая другая ссылка на него по-прежнему будет иметь старую копию!

Единственный путь вокруг этого - отслеживать этот массив с одним дополнительным уровнем косвенности - т.е.: Используйте указатель на динамический массив (который также является указателем сам по себе, но это хорошо).

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


Мне все хорошо, если вы измените последнюю строку на

SetLength(List, Length(List), y + 1);


@PatrickvL: Извините, но это просто неправильно. Ваш код даже не компилируется, потому что он пытается установить два измерения для одномерного элемента List [x]. (PatrickvL обновил свой код, чтобы эта часть ответа больше не действительна.)

Следующий код демонстрирует многомерное изменение размера массива.

программа TestDimensions;

{$APPTYPE CONSOLE}
uses
 SysUtils;
var
 List: array of array of integer;
begin
 //set both dimensions
 SetLength(List, 3, 2);
 Writeln('X = ', Length(List), ', Y = ', Length(List[0])); //X = 3, Y = 2
 //set main dimension to 4, keep subdimension untouched
 SetLength(List, 4);
 Writeln('X = ', Length(List), ', Y = ', Length(List[0])); //X = 4, Y = 2
 //set subdimension to 3, keep main dimenstion untouched
 SetLength(List, Length(List), 3);
 Writeln('X = ', Length(List), ', Y = ', Length(List[0])); //X = 4, Y = 3
 //all List[0]..List[3] have 3 elements
 Writeln(Length(List[0]), Length(List[1]), Length(List[2]), Length(List[3])); //3333
 //you can change subdimension for each List[] vector
 SetLength(List[0], 1);
 SetLength(List[3], 7);
 //List is now a ragged array
 Writeln(Length(List[0]), Length(List[1]), Length(List[2]), Length(List[3])); //1337
 //this does not even compile because it tries to set dimension that does not exist!
// SetLength(List[0], Length(List[0]), 12);
 Readln;
end.

Справка Delphi также объясняет это довольно хорошо (Structured Types, Arrays).

Многомерные динамические массивы Чтобы объявить многомерные динамические массивы, используйте итеративный массив... конструкций. Например,

type TMessageGrid = массив массива строки; var Msgs: TMessageGrid;

объявляет двумерный массив строк. Чтобы создать экземпляр этого массива, вызовите SetLength с двумя целыми аргументами. Например, если я и J - целые значащие переменные,

SetLength (Msgs, I, J);

выделяет массив I-by-J, а Msgs [0,0] обозначает элемент этого массива.

Вы можете создавать многомерные динамические массивы, которые не являются прямоугольными. Первым шагом является вызов SetLength, передача его параметров для первых n измерений массива. Например,

var Ints: массив массива Integer, SetLength (Интс, 10);

выделяет десять строк для Ints, но без столбцов. Позже вы можете выделять столбцы по одному (давая им разные длины); например

SetLength (Ints [2], 5);

делает третий столбец из пяти целых чисел Ints длинным. В этот момент (даже если другие столбцы не были выделены) вы можете назначить значения для третьего столбца - например, Ints [2,4]: = 6.

В следующем примере используются динамические массивы (и функция IntToStr, объявленные в модуле SysUtils) для создания треугольной матрицы строк.

вар   A: массив массива строки;   I, J: Integer,   начать     SetLength (A, 10);     для I: = Низкий (A) - высокий (A) do       начать         SetLength (A [I], I);         для J: = Низкий (A [I]) до Высокого (A [I]) делать           A [I, J]: = IntToStr (I) + ',' + IntToStr (J) + '';       конец;   конец;

licensed under cc by-sa 3.0 with attribution.