Рейтинговые книги
Читем онлайн Советы по Delphi. Версия 1.4.3 от 1.1.2001 - Валентин Озеров

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 7 8 9 10 11 12 13 14 15 ... 123

SetLength(VarArray, Razmernost1); // У первого измерения

SetLength(VarArray[1], Razmernost2); // У второго измерения первой «строки»

SetLength(VarArray[2], Razmernost3); // У второго измерения второй «строки»

SetLength(VarArray[n], Razmernost4); // У второго измерения n-ной «строки»

SetLength(VarArray[1][1], Razmernost5); // У третьего измерения первой «строки» первого «столбца»

SetLength(VarArray[1][2], Razmernost6); // У третьего измерения первой «строки» второго «столбца»

SetLength(VarArray[n][m], Razmernost7); // У третьего измерения n-ной «строки» m-ного «столбца»

т.д.

Все можно изменять в процессе естественно.

3. Получение длин

Razmernost1:=Length(VarArray); // У первого измерения (количество строк)

Razmernost2:=Length(VarArray[1]); // У второго измерения первой «строки» (количество столбцов)

Razmernost3:=Length(VarArray[2]); // У второго измерения второй «строки» (количество столбцов)

Razmernost4:=Length(VarArray[n]); // У второго измерения n-ной «строки» (количество столбцов)

Razmernost5:=Length(VarArray[1][1]); // У третьего измерения первой «строки» первого «столбца»

Razmernost6:=Length(VarArray[1][2]); // У третьего измерения первой «строки» второго «столбца»

Razmernost7:=Length(VarArray[n][m]); // У третьего измерения n-ной «строки» m-ного «столбца»

4. Обращение

VarArray[n][m][o][p][r]:=1; // :Integer // К элементу n-ной «строки», m-ного «столбца», // o-того «?», p-того «?», r-того «?»

5. Обнуление (освобождение памяти)

SetLength (VarArray, 0); // Всех сразу

Динамические массивы VI

Delphi 1

Например, если вам необходимо сохранить «GIZMOS» в вашем массиве, сделайте следующее:

CONST

 MaxGIZMOS = $FFFF Div (SizeOf(GIZMOS)) { или что-то другое, смотря какой максимальный размер GIZMOS вы планируете...}

TYPE

 pGIZMOArray = ^GIZMOArray;

 GIZMOArray  = Array[1..MaxGIZMOS] of GIZMOS;

VAR

 TheGIZMOS: pGIZMOArray;

 GIZMOcount: integer;

BEGIN

 GetMem(TheGIZMOS,(GIZMOcount+1)*SizeOf(GIZMO)); {Нужна дополнительная единица, поскольку массив GetMem ведет отсчет с нуля…}

 TheGIZMOS^[index] := Whatever;

ну и так далее…

TList — такой динамический массив. Для получения дополнительной информации обратитесь к электронной справке. Если вы хотите это делать сами, то вам необходимо использовать GetMem для получения указателя на распределенную динамическую память, и затем FreeMem для освобождения памяти, занятой динамическим массивом. Tlist сделает это за вас самым надежным образом.

Динамические массивы VII

Delphi 1

Существует несколько способов сделать это. Применять тот или иной способ зависит от того, какой массив вы используете — массив строк или массив чисел (целые, натуральные и пр.).

1. Если вам необходим простой динамический одномерный массив строк, я предлагаю вам взглянуть на компонент tStringList, он сам заботится о функциях управления и легок в использовании.

2. Если вам необходим динамический многомерный массив строк, вы также можете воспользоваться tStringList (в случае, если число элементов вашего массива не превышает лимит для tStringList, я полагаю он равен 16,000). Чтобы сделать это, создайте функцию линейного распределения как показано ниже:

Допустим у вас есть трехмерный массив строк, текущее измерение [12,80,7], и вы хотите найти элемент [n,m,x]. Вы можете найти этот элемент в приведенном одномерном массиве с помощью формулы ((n-1)*80*7 + (m-1)*80 + x). Затем вы можете использовать это в качестве индекса в tStringList. Для диманического изменения одной из границ массива, используйте метод tStringList Move, служащий как раз для таких целей. (Метод состоит из некоторых технологических внутренних циклов, но выполняются они очень быстро, поскольку tStringList манипулирует не с самими строками, а с указателями на них.)

3. Если вам необходим динамический одномерный массив чисел, то в общих словах я приведу его ниже, но есть масса мелких деталей. Объявите указатель на тип массива, имеющего максимальное количество элементов данного типа (помните о том, что Delphi-16 позволяет иметь типам область памяти, ограниченной 64K), например так:

type

 bigArray: array[1..32000] of integer;  {или ^double, или что-то еще}

 pMyArray: ^bigArray;

затем распределите сам массив:

getMem (pMyArray, sizeof(integer) * n);

где n — количество элементов. После этого вы можете ссылаться на элементы массива следующим образом:

pMyArray^[51]

Не забудьте освободить массив с помощью FreeMem после того, как вы его использовали.

Изменить размер массива, определить новый указатель, перераспределить или обменяться с другим массивом можно так:

pTemp: ^bigArray;

getMem(pTemp, sizeof(integer) * newnumelements);

memcopy(pTemp, pMyArray, sizeof(integer)*n);

{n – количество элементов в pMyArray}

freeMem(pMyArray, sizeof(integer)*n);

pMyArray := pTemp;

4. Если вам необходим многомерный массив чисел, скомбинируйте технику, описанную в пункте (3), с функцией распределения, описанной в пункте (2).

5. Если для вашего массива необходим участок памяти больше чем 64K, вам необходимо разработать список указателей на участки памяти, но эта тема выходит за рамки данной статьи.

Лично я инкапсулировал все в своем объекте. Я использую, как я это называю, «Basic String Object» (BSO), базовый строковый объект, который осуществляет динамическое распределение и освобождение памяти для строк любого размера. Непосредственно это PChar, указывающий на распределенную память. У меня существует два внешних свойства: AsString и AsPChar. Также у меня есть различные свойства и методы, позволяющие иметь различные способы доступа и манипулировать строками.

Я написал свои собственные malloc(), calloc() и realloc(), используя частные методы объекта TString для сканирования распределенной памяти. Это классно работает, когда мне нужно «захватить» блок памяти.

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

О другой идее я уже рассказывал (открытый массив). Если вам нужна проверка выхода за границы и/или динамическое изменение размера массива, вы можете использовать метод, аналогичный методу работы со строковым объектом (описанный мною выше), но вам необходимо будет интегрировать свойство-массив по умолчанию, чтобы иметь к нему простой доступ. Это позволит вам иметь индексы и использовать нужный вам тип.

TMyDynamicObject =

 …

 PROPERTY Array[idx:LONGINT]:TMyType READ GetArray WRITE PutArray DEFAULT;

VAR Mine :TMyDynamicObject;

Mine := TMyDynamicObject.Create;

FOR i := 10 TO 20 DO Mine[i] := {значение}

{ЧУДОВИЩНАЯ РАСТРАТА ПАМЯТИ - если вы действительно используете такие большие массивы и хэш-таблицы }

Mine[-100000] := {значение}

Mine[+100000] := {значение}

Если в вашем распоряжении находится «редкозаполненный» массив, использование хэш-таблицы дало бы существенный выигрыш. Я преобразую индексные значения в строки, а все остальное перепоручаю TStrings, но не из-за того, что я такой ленивый, а из-за того, что он сделает это лучше меня, мне нужно всего лишь осуществить преобразование в строки.

Для того, чтобы хранить все, что вы хотите, вы можете использовать TList (или TStringList.Objects)! TList.Items хранят указатели на объекты или записи, но они ничего не могут сделать с ними, поэтому вы можете привести их к типу longint, и больше о них не беспокоиться! Вот пример хранения в TList списка целых:

var

 aList: TList;

 I : Integer;

 L : Longint;

begin

 aList := TList.Create;

 L := 93823;

 aList.Add(Pointer(L));

 aList.Add(Pointer(83293));

 for I := 1 to aList.Count do L := L + Longint(aList.Items[I-1]);

 aList.Free;

end;

В TList и TStringList вы можете иметь до 16380 элементов. А теперь обещанный пример того, как можно хранить в TList записи (или объекты), вернее, указатели на них:

type

 PMyRec = TMyRec;

 TMyRec = record

  Name: string[40];

  Addr : string[25];

  Comments: string;

  salary: Double;

 end;

var

 aList: TList;

 aRecPtr: PMyRec;

 I : Integer;

begin

 aList := TList.Create;

 New(aRecPtr);

 with aRecPtr^ do begin

  Name := 'Валентин';

  Addr := 'неизвестен';

1 ... 7 8 9 10 11 12 13 14 15 ... 123
На этой странице вы можете бесплатно читать книгу Советы по Delphi. Версия 1.4.3 от 1.1.2001 - Валентин Озеров бесплатно.

Оставить комментарий