Основи на Delphi

Една от най-мощните характеристики на езика Delphi са динамичните масиви. Основната им разлика от обикновените масиви е, че се съхраняват в динамична памет. Това е причината за името им. За да разберете защо са необходими, разгледайте пример:

var N: Цяло число; A: масив [1..100] от цяло число; // обикновен масив begin Write('Въведете броя на елементите: '); ЧетенеLn(N); . край.

var N: Цяло число; A: масив [1..N] от цяло число; // Грешка! begin Write('Въведете брой елементи: '); ЧетенеLn(N); . край.

На етапа на писане на програма е невъзможно да се предвиди точно какво количество данни ще иска да обработи потребителят. Ще трябва обаче да отговорите на два важни въпроса:

Колко елемента да се декларира един масив?

Ами ако потребителят все още се нуждае от още елементи? Можете да направите следното. Като горна граница на масива задайте максималния възможен (от ваша гледна точка) брой елементи, но всъщност използвайте само част от масива. Ако потребителят се нуждае от повече артикули от резервираните от вас, можете просто да му откажете учтиво. Например:

const MaxNumberOfElements = 100; променлива N: Цяло число; A: масив [1..MaxNumberOfElements] от цяло число; begin Write('Въведете броя на елементите (не повече от ', MaxNumberOfElements, '): '); ЧетенеLn(N); ако N>gt; MaxNumberOfElements след това започнете Write('Съжаляваме, програмата не може да работи'); Writeln('с брой елементи по-голям от , ' MaxNumberOfElements, '.'); край иначе започнете . // Инициализирайте масива с необходимите стойности и го обработете end; край.

Това решение на проблема не е оптимално. Акопотребителят се нуждае само от 10 елемента, програмата работи без проблеми, но винаги използва количеството памет, необходимо за съхраняване на 100 елемента. Паметта, разпределена за останалите 90 елемента, няма да се използва от вашата програма или други програми (според принципа "Няма да я дам на друг"). Сега си представете, че всички програми правят същото. Ефективността на използването на RAM рязко пада.

Динамичните масиви ни позволяват да решим разглеждания проблем по възможно най-добрия начин. Размерът на динамичен масив може да се променя, докато програмата работи.

Динамичен масив се декларира без граници:

var DynArray: масив от цели числа;

Променливата DynArray е препратка към елементи на масив, разпределени в динамична памет. Първоначално не е запазена памет за масива, броят на елементите в масива е нула, а стойността на променливата DynArray е нула.

Работата с динамични масиви е подобна на работата с дълги низове. По-специално, създаването на динамичен масив (разпределяне на памет за неговите елементи) се извършва чрез същата процедура, която задава дължината на низовете - SetLength.

SetLength(DynArray, 50); // Заделяне на памет за 50 елемента

Промяната на размера на динамичен масив се извършва по същата процедура: SetLength(DynArray, 100); // Сега размерът на масива е 100 елемента

Когато масивът бъде преоразмерен, стойностите на всички негови елементи се запазват. В този случай последователността от действия е следната: разпределя се нов блок памет, стойностите на елементите от стария блок се копират в новия и старият блок памет се освобождава.

Когато размерът на динамичния масив се намали, допълнителните елементи се губят.

При увеличаване на размера на динамичен масив, добавенатаелементите не се инициализират с никаква стойност и като цяло техните стойности са произволни. Ако обаче динамичният масив се състои от елементи, чийто тип предполага автоматично инициализиране на празна стойност (низ, вариант, динамичен масив и т.н.), тогава добавената памет се инициализира на нула.

Броят на елементите се определя с помощта на функцията Length:

N := Дължина(DynArray); // N ще бъде зададено на 100

Елементите на динамичен масив винаги се индексират от нула. Достъпът до тях не се различава от достъпа до елементи на обикновени статични масиви:

DynArray[0] := 5; // Задаване на начален елемент на 5 DynArray[High(DynArray)] := 10; // задайте крайния елемент на 10

За динамичните масиви, както и за обикновените масиви, са приложими функциите Low и High, които връщат съответно минималния и максималния индекс на масива. За динамични масиви функцията Low винаги връща 0.

Освобождаването на паметта, разпределена за елементите на динамичен масив, се извършва чрез задаване на дължината на 0 или чрез присвояване на променливата на масива на нула (и двете опции са еквивалентни):

SetLength(DynArray, 0); // Еквивалент: DynArray := nil;

Въпреки това, не е нужно да освобождавате разпределената памет, когато приключите с използването на динамичния масив, защото тя се освобождава автоматично, когато излезете от обхвата на променливата на масива (удобно, нали!). Тази възможност се предоставя от механизма за отчитане на броя на вече известните ви препратки.

Точно както при работа с низове, при присвояването на един динамичен масив към друг не се създава копие на вече съществуващ масив.

var A, B: масив от цели числа; започнете SetLength(A, 100); // Разпределяне на памет за 100елементи A[0] := 5; B := A; // A и B сочат към една и съща област на паметта! B[1] := 7; // Сега A[1] също е 7! B[0] := 3; // Сега A[0] е 3, а не 5! край.

Както при низовете, паметта се освобождава, когато броят на препратките стане нула.

var A, B: масив от цели числа; започнете SetLength(A, 100); // Разпределяне на памет за 100 елемента A[0] := 10; B := A; // B сочи към същите елементи като A A := nil; // Паметта все още не е освободена, защото към нея сочи B B[1] := 5; // Продължете с B, B[0] = 10 и B[1] = 5 B := nil; // Сега няма препратки към блока памет. Паметта се освобождава end;

За да работите с динамични масиви, можете да използвате познатата функция за копиране от низове. Той връща част от масива като нов динамичен масив.