Таблица StringGrid состоит из выделенных серым FixedCols и FixedRows - зафиксированных ячеек-заголовков, и обычных, белых ячеек. Содержимое Fixed ячеек недоступно редактированию, и меняется только программно. За возможность редактирования обычных ячеек отвечает одно из значений свойства Options.
Понятие блока в современных языках программирования. Формальные параметры и фактические значения параметров блока. 19. Понятие процедуры в современных языках программирования. Формальные параметры и фактические значения параметров процедур. Возможны ли процедуры без параметров? 20. Понятие функции в современных языках программирования. Формальные параметры и фактические значения параметров функции. Отличие функции от процедуры – в структуре и по содержанию.
Очевидно, что встроенных процедур и функций для решения большинства прикладных задач недостаточно, поэтому приходиться придумывать собственные процедуры и функции. По своей структуре они очень напоминают программу и состоят из заголовка и блока . Заголовок процедуры состоит из зарезервированного слова procedure, имени процедуры и необязательного заключенного в круглые скобки списка формальных параметров . Имя процедуры — это идентификатор, уникальный в пределах программы. Формальные параметры — это данные, которые вы передаете в процедуру для обработки, и данные, которые процедура возвращает (подробно параметры описаны ниже). Если процедура не получает данных извне и ничего не возвращает, формальные параметры (в том числе круглые скобки) не записываются. Тело процедуры представляет собой локальный блок , по структуре аналогичный программе:
procedure <имя процедуры> ( <список формальных параметров > ) ;
const ...;
type ...;
var ...;
begin
<операторы>
end;
Описания констант, типов данных и переменных действительны только в пределах данной процедуры. В теле процедуры можно использовать любые глобальные константы и переменные, а также вызывать любые подпрограммы (процедуры и функции).
Вызов процедуры для выполнения осуществляется по ее имени, за которым в круглых скобках следует список фактических параметров , т.е. передаваемых в процедуру данных:
Если процедура не принимает данных, то список фактических параметров (в том числе круглые скобки) не указываются.
Понятие процедуры является чрезвычайно важным, так как именно оно лежит в основе одной из самых популярных технологий решения задач на языке Delphi. Технология эта внешне проста: задача разбивается на несколько логически обособленных подзадач и решение каждой из них оформляется в виде отдельной процедуры. Любая процедура может содержать в себе другие процедуры, их количество ограничено только объемом памяти вашего компьютера.
Приведем пример небольшой программы, использующей процедуру Power для вычисления числа X в степени Y. Результат вычисления процедура Power заносит в глобальную переменную Z.
program Console;
{$APPTYPE CONSOLE}
uses
SysUtils;
var
Z: Double;
procedure Power(X, Y: Double); // X и Y - формальные параметры
begin
Z := Exp(Y * Ln(X));
end;
begin
Power(2, 3); // 2 и 3 - фактические параметры
Writeln('2 в степени 3 = ', Z);
Writeln('Press Enter to exit...');
Readln;
end.
Функции программиста применяются в тех случаях, когда надо создать подпрограмму, участвующую в выражении как операнд. Как и процедура, функция состоит из заголовка и блока . Заголовок функции состоит из зарезервированного слова function, имени функции, необязательного заключенного в круглые скобки списка формальных параметров и типа возвращаемого функцией значения . Функции возвращают значения любых типов данных кроме Text и file of (см. файлы). Тело функции представляет собой локальный блок , по структуре аналогичный программе.
function <имя функции> ( <список формальных параметров > ): <тип результата>;
const ...;
type ...;
var ...;
begin
<операторы>
end;
В теле функции должен находиться по крайней мере один оператор, присваивающий значение имени функции или неявной локальной переменной Result. Если таких присваиваний несколько, то результатом функции будет значение последнего из этих операторов. Преимущество от использования переменной Result состоит в том, что она может участвовать в выражениях как операнд.
В качестве примера заменим явно неуклюжую процедуру Power (см. выше) на функцию с таким же именем:
program Console;
{$APPTYPE CONSOLE}
uses
SysUtils;
function Power(X, Y: Double): Double; // X и Y - формальные параметры
begin
Result := Exp(Y * Ln(X));
end;
begin
Writeln('2 в степени 3 = ', Power(2, 3)); // 2 и 3 - фактические параметры
Writeln('Press Enter to exit...');
Readln;
end.
Параметры служат для передачи исходных данных в подпрограммы и для приема результатов работы этих подпрограмм.
Исходные данные передаются в подпрограмму с помощью входных параметров, а результаты работы подпрограммы возвращаются через выходные параметры . Параметры могут быть входными и выходными одновременно.
Входные параметры объявляются с помощью ключевого слова const; их значения не могут быть изменены внутри подпрограммы:
function Min(const A, B: Integer): Integer;
begin
if A < B then Result := A
else Result := B;
end;
Для объявления выходных параметров служит ключевое слово out:
Установка значений выходных параметров внутри подпрограммы приводит к установке значений переменных, переданных в качестве аргументов:
var
W, H: Integer;
begin
GetScreenResolution(W, H);
...
end;
После вызова процедуры GetScreenResolution переменные W и H будут содержать значения , которые были присвоены формальным параметрам Width и Height соответственно.
Если параметр является одновременно и входным, и выходным, то он описывается с ключевым словом var:
procedure Exchange(var A, B: Integer);
var
C: Integer;
begin
C := A;
A := B;
B := C;
end;
Изменение значений var-параметров внутри подпрограммы приводит к изменению значений переменных, переданных в качестве аргументов:
var
X, Y: Integer;
begin
X := 5;
Y := 10;
...
Exchange(X, Y);
// Теперь X = 10, Y = 5
...
end;
При вызове подпрограмм на место out- и var-параметров можно подставлять только переменные, но не константы и не выражения.
Если при описании параметра не указано ни одно из ключевых слов const, out, или var, то параметр считается входным, его можно изменять, но все изменения не влияют на фактический аргумент, поскольку они выполняются с копией аргумента, создаваемой на время работы подпрограммы. При вызове подпрограммы на месте такого параметра можно использовать константы и выражения. Пример подпрограммы:
function NumberOfSetBits(A: Cardinal): Byte;
begin
Result := 0;
while A <> 0 do
begin
Result := Result + (A mod 2);
A := A div 2;
end;
end;
Параметр A в приведенной функции является входным, но при этом он используется в качестве локальной переменной для хранения промежуточных данных.
Разные способы передачи параметров (const, out, var и без них) можно совмещать в одной подпрограмме. В следующем законченном примере процедура Average принимает четыре параметра. Первые два (X и Y) являются входными и служат для передачи исходных данных. Вторые два параметра являются выходными и служат для приема в вызывающей программе результатов вычисления среднего арифметического (M) и среднего геометрического (P) от значений X и Y:
program Console;
{$APPTYPE CONSOLE}
uses
SysUtils;
procedure Average(const X, Y: Double; out M, P: Double);
begin
M := (X + Y) / 2;
P := Sqrt(X * Y);
end;
var
M, P: Double;
begin
Average(10, 20, M, P);
Writeln('Среднее арифметическое = ', M);
Writeln('Среднее геометрическое = ', P);
Writeln('Press Enter to exit...');
Readln;
end.
Существует разновидность параметров без типа. Они называются нетипизированными и предназначены для передачи и для приема данных любого типа. Нетипизированные параметры описываются с помощью ключевых слов const и var, при этом тип данных опускается:
procedure JustProc(const X; var Y; out Z);
Внутри подпрограммы тип таких параметров не известен, поэтому программист должен сам позаботиться о правильной интерпретации переданных данных. Заметим, что при вызове подпрограмм на место нетипизированных параметров (в том числе и на место нетипизированных const-параметров) можно подставлять только переменные.
Передача фактических аргументов в подпрограмму осуществляется через специальную область памяти — стек. В стек помещается либо значение передаваемого аргумента (передача значения), либо адрес аргумента (передача ссылки на значение). Конкретный способ передачи выбирается компилятором в зависимости от того, как объявлен параметр в заголовке подпрограммы. Связь между объявлением параметра и способом его передачи поясняет таблица 2.10:
Ключевое слово
Назначение
Способ передачи
<отсутствует>
Входной
Передается копия значения
const
Входной
Передается копия значения либо ссылка на значение в зависимости от типа данных
out
Выходной
Передается ссылка на значение
var
Входной и выходной
Передается ссылка на значение
Таблица 2.10. Способы передачи параметров
Если передается значение, то подпрограмма манипулирует копией аргумента. Если передается ссылка на значение, то подпрограмма манипулирует непосредственно аргументом, обращаясь к нему через переданный адрес.
В языке Delphi существует возможность задать параметрам процедур и функций стандартные значения. Они указываются через знак равенства после типа параметра. Например, опишем процедуру, которая заполняет некоторую область памяти заданным значением:
Подпрограмма может содержать любое количество параметров со стандартными значениями, однако такие параметры должны быть последними в списке. Другими словами, после параметра со стандартным значением не может следовать обычный параметр, поэтому следующее описание будет воспринято компилятором как ошибочное:
Что такое событийное программирование? Понятие события и его роль в современном программировании. 22. События в Делфи программах, их назначения, средства реализации, примеры разнообразных событий.
Примеры событий в конкретных программах на Делфи.
Событийный подход к программированию включает использование объектов, способных реагировать на события, происходящие в системе. Событийный подход используется при разработке как самостоятельных программ, так и операционных систем, например, Microsoft Windows или OS/2 Presentation Manager.
Строго говоря, событийное программирование не имеет прямого отношения к объектному, примером чему является Windows, в которой изначально предполагалось создание программ на языке C, не имеющем средств ООП. Однако, как показывает практика, событийный подход имеет довольно много общего с объектным. В первую очередь это инкапсуляция данных, а также полиморфизм и в ряде случаев наследование. Это означает, что при реализации событийного подхода удобно использовать средства ООП -- в этом случае многие особенности событийных программ реализуются автоматически.
С использованием событийного и объектного подходов в настоящее время построен целый класс библиотек -- шаблоны программ (Application Frameworks). Такие библиотеки могут включать как собственный диспетчер событий (как, например, Turbo Vision фирмы Borland), так и полагаться на средства операционной системы (например, библиотеки для Windows OWL фирмы Borland и MFC фирмы Microsoft). Визуальные компоненты способны генерировать и обрабатывать достаточно большое число (несколько десятков) событий различных видов. К наиболее общим группам событий можно отнести следующие:
· выбор элемента управления;
· перемещение указателя мыши;
· вращение колеса мыши;
· нажатие клавиш;
· получение и потеря элементом управления фокуса ввода;
· перемещение объектов методом drag-and-drop (перетаскиванием).
Отметим, что в окне Инспектора объектов события сгруппированы по следующим группам:
· действие (Action);
· перемещение и стыковка компонентов (Drag, Drop and Docking);
· контекстная помощь (Help and Hints);
· входные (Input);
· среда (Layout);
· связь (Linkage);
· разное (Miscellaneous);
· визуальные (Visual).
Объекты из библиотеки визуальных компонент (VCL) Delphi, равно как и объекты реального мира, имеют свой набор свойств и свое поведение - набор откликов на события, происходящие с ними. Список событий для данного объекта, на которые он реагирует, можно посмотреть, например, в Инспекторе Объектов на странице событий. (На самом деле, на этой странице представлен список свойств, которые имеют тип вроде TMouseMoveEvent и представляют из себя процедуры-обработчики событий. Существует соглашение по названиям данных свойств. Например, OnDblClick соответствует двойному щелчку мыши, а OnKeyUp - событию, когда нажатая клавиша была отпущена.) Среди набора событий для различных объектов из VCL есть как события, портируемые из Windows (MouseMove, KeyDown), так и события, порождаемые непосредственно в программе (DataChange для TDataSource).
Поведение объекта определяется тем, какие обработчики и для каких событий он имеет. Создание приложения в Delphi состоит из настройки свойств используемых объектов и создания обработчиков событий.
Простейшие события, на которые иногда нужно реагировать - это, например, события, связанные с мышкой (они есть практически у всех видимых объектов) или событие Click для кнопки TButton. Предположим, что вы хотите перехватить щелчок левой кнопки мыши на форме. Чтобы сделать это - создайте новый проект, в Инспекторе Объектов выберите страницу событий и сделайте двойной щелчок на правой части для свойства OnClick. Вы получите заготовку для обработчика данного события:
Каждый раз, когда делается щелчок левой кнопки мыши над формой будет появляться окно диалога (см. рис.1).
Рис.1: Диалог, появляющийся при щелчке мыши на форме.
Код, приведенный выше, представляет из себя простейший случай ответа на событие в программе на Delphi. Он настолько прост, что многие программисты могут написать такой код и без понимания того, что они на самом деле отвечают на сообщение о событии, посланное им операционной системой. Хотя программист получает это событие через третьи руки, тем не менее он на него отвечает.
Опытные программисты в Windows знают, что при возникновении события, операционная система передает вам не только уведомление о нем, но и некоторую связанную с ним информацию. Например, при возникновении события "нажата левая кнопка мыши" программа информируется о том, в каком месте это произошло. Если вы хотите получить доступ к такой информации, то должны вернуться в Инспектор Объектов и создать обработчик события OnMouseDown:
Как видите, в Delphi очень просто отвечать на события. И не только на события, связанные с мышкой. Например, можно создать обработчик для OnKeyDown (нажата клавиша):
Теперь, когда вы имеете начальные знания о программировании событий в Delphi, самое время вернуться назад и посмотреть на теорию, стоящую за тем кодом, что вы написали. После получения представления о том, как работает система, можно вернуться к среде Delphi и посмотреть, как использовать полностью имеющиеся возможности.
Составные имена в программах – когда они возникают, как формируются и с помощью каких средств можно сократить длину таких имен. (например, оператор With)
Инструкция доступа служит для удобной и быстрой работы с составными частями объектов, в том числе с полями записей. Напомним, что для обращения к полю записи необходимо указывать имя записи и имя этого поля, разделенные точкой. Аналогичным путем образуется имя составной части какого-либо объекта, например, формы или кнопки.
Инструкция доступа имеет следующий основной формат:
Формат инструкции доступа
1. with < Имя объекта> do <Инструкция>
В Инструкции, расположенной после слова do, для обращения к составной части объекта можно не указывать имя этого объекта, которое уже задано после слова with.
Вот пример двух вариантов обращения к составным частям объекта:
Формат инструкции доступа
1. // Составные имена пишутся полностью
2. Form1.Canvas.Pen.Color := clRed;
3. Form1.Canvas.Pen.Width := 5;
4. Form1.Canvas.Rectangle(10, 10, 100, 100);
5. // ИЛИ
6. // Использование инструкции доступа
7. with Form1. Canvas do
8. begin
9. Pen.Color := clRed;
10. Pen.Width := 5;
11. Rectangle(10, 10, 100, 100);
12. end;
В обоих вариантах в форме красным карандашом толщиной в пять пикселов рисуется прямоугольник. Для обращения к свойствам и методу (процедуре) поверхности рисования формы удобно использовать инструкцию доступа (второй вариант).
В инструкции доступа допускается указывать несколько имен объектов.
Формат инструкции доступа
1. with < Имя объекта1>,..., < Имя объектаЫ> do <Инструкция>
2. // Такой формат эквивалентен следующей конструкции:
3. with < Имя объекта1> do
4. with < Имя объекта2> do
5. ...
6. with < Имя объектаN> do
7. <Инструкция>
В этом случае для составной части имени объекта, если возможно, применяется < имя объектаN>, иначе — < Имя объектаN-1> и т. д. до < Имя объекта1>.
ПРИМЕР ИСПОЛЬЗОВАНИЯ СОСТАВНЫХ ИМЕН В ПРОГРАММЕ:
Begin Memo1.Text:=’Учиться в МГУПИ мне интересно’;
Запись как тип данных, их определение, назначение, структура. Обращение к полям записей: составные имена, оператор With. Примеры применения в программах.
Запись (англ. record) - это сложный тип данных, позволяющие объединить данные разных типов. Запись можно назвать наиболее общим сложным типом данных. Название "запись" появилось из тех соображений, что данные разного типа можно встретить в таблицах: в каждой строке записаны сразу несколько разных значений. Таким образом, одна запись соответствует одной строке данных: она имеет несколько полей, каждое из которых хранит своё значение.
Допустим, мы хотим хранить информацию о людях, заполнивших анкету на поступление на работу. Нас интересуют: ФИО человека, возраст, образование (среднее/высшее), владение компьютером, владение иностранными языками. Все эти данные мы можем объединить в запись. Дальнейшее повествование будет основываться на этом примере.
Чтобы работать в программе с записями, нужно сначала описать соответствующий тип данных. Запись описывается следующим образом:
type
имя_типа_записи = record
{поля записи}
end;
В блоке полей описание идёт точно так же, как описание переменных: указывается имя поля, далее через двоеточие тип данных этого поля. Сами поля разделяются точкой с запятой.
Для нашего примера:
type
TPerson = record
Name: String;
Age: Byte;
Education,PC: Boolean;
Foreign: set of TForeignLanguages;
end;
Итак, общая форма записи:
with запись do
{обращение к полям записи}
А теперь на нашем примере:
with L do
begin
X:=StrToFloat(X1Edit.Text);
Y:=StrToFloat(Y1Edit.Text);
X2:=StrToFloat(X2Edit.Text);
Y2:=StrToFloat(Y2Edit.Text);
end;
Что же мы имеем? А вот что: мы нашу запись "вынесли за скобку", и далее напрямую обращаемся к её полям. Удобно, не правда ли? Этот код абсолютно эквивалентен тому, что был написан нами ранее, только он более эффективен.
Несложно догадаться, что использование with для единичного обращения к записи бессмысленно/
Записи объединяют фиксированное число элементов данных других типов. Отдельные элементы записи имеют имена и называются полями. Имя поля должно быть уникальным в пределах записи. Различают фиксированные и вариантные записи.
Фиксированная запись состоит из конечного числа полей, ее объявление имеет формат:
Фиксированная запись
1. Record
2. <Имя поля1> : <Тип поля1>;
3. ...
4. <Имя поляN> : <Тип поляN>;
5. end;
Вариантная запись, как и фиксированная, имеет конечное число полей, однако предоставляет возможность по-разному интерпретировать области памяти, занимаемые полями. Все варианты записи располагаются в одном месте памяти и позволяют обращаться к ним по различным именам. Отметим, что в данном случае термин «вариантный» не имеет ничего общего с вариантным типом (variant). Формат объявления вариантной записи:
Вариантная запись
1. Record
2. case <Признак> : <Тип признака> of
3. <Вариант1> : (<Описание варианта1>);
4. <ВариантN> : (<Описание вариантаN>);
5. end;
Для обращения к конкретному полю необходимо указывать имя записи и имя поля, разделенные точкой, т. е. имя поля является составным. С полем можно выполнять все операции, которые допускаются для отдельной переменной этого же типа.
Пример использования записи:
Пример использования записи
1. var
2. Man: record
3. Name: string;
4. Salary: real;
5. Note: string;
6. end;
7. Man.Name: = 'Иванов M.P.';
8. Man.Salary:=500;
Переменная Man является фиксированной записью и имеет поля имени (Name), оклада (Salary) и примечания (Note), каждое своего типа.
Система Delphi предоставляет также большое количество уже описанных типов записей, например:
Пример использования записи
1. type
2. TPoint = record
3. X: Longint;
4. Y: Longint;
5. end;
6. TRect = record
7. case Integer of
8. 0: (Left, Top, Right, Bottom: Integer);
9. 1: (TopLeft, BottomRight: TPoint);
10. end;
Здесь тип TPoint является фиксированной записью, а тип TRect— вариантной записью.
Условный оператор, его назначение, структура. Варианты условных операторов. Вложенные условные операторы. Примеры.
С помощью условного оператора происходит проверка заданного условия и в зависимости от полученного результата происходит выбор одного из двух действий. Условный оператор представляет средство ветвления алгоритмического процесса.
Структура условного оператора представляет собой следующий вид:
if условие then список операторов 1 else список операторов 2 ;
где if, then, else - зарезервированные слова, по русски означающие - если, то, иначе.
Условие выбора - это логическое выражение (в основном используются операторы сравнения).
список операторов 1 и список операторов 2 - любые операторы языка Delphi. В состав списка операторов может входить один оператор или несколько, тогда это должен быть составной оператор. Один из выборов может отсутствовать, (быть пустым). Обычно это выбор действий расположенный после слова else. В такой ситуации, при условии равном FALSE, управление передается операторам следующим сразу за условным оператором.
Алгоритм работы условного оператора имеет следующий вид. Первоначально вычисляется выражение условие. Получаем результат логического типа. Если результат равен TRUE, то выполняются операторы входящие в список операторов 1, а список операторов 2 пропускается. Если результат равен FALSE, то происходит обратное действие - выполняются операторы входящие в список операторов 2, а список операторов 1 пропускается.
Еще важный момент перед словом else не ставиться точка c запятой.
Давайте расположим на форме кнопку Button и компонент Label. Для кнопки напишем такой обработчик события:
procedure TForm1.Button1Click(Sender: TObject);
var
i : integer;
begin
i :=2;
if i = 1 then
begin
Label1.Caption := 'Переменная i равна 1';
Form1.Color := clRed
end else
begin
Label1.Caption := 'Переменная i не равна 1';
Form1.Color := clGray
end
end;
Изменяя значение переменной i с 1 на двойку мы увидим работу условного оператора в действии. Как результат будет выбор цвета формы и название заголовка компонента label.
Если условие сложное и само в себе включает несколько условий, то их необходимо объединить путем организации вложений условных операторов или используя логические операторы and, or, xor, not.
В сложных логических выражениях отдельные части-условия необходимо заключать в скобки:
if (i > y) and (j = 55) then ...
Запись без скобок будет ошибочной, так как компилятор воспримет его следущим образом:
if i > (y and j) = 55 then ...
Список операторов 1 и список операторов 2 могут содержать любые операторы, в том числе содержать условные операторы. В свою очередь любой из вложенных может содержать в себе еще условные операторы. Бывает не у всех вложенных условных операторах имеется слово else. В этих случаях следует исходить из того, что else всегда ассоциируется с ближайшим к нему (сверху по тексту) словом if, которое еще не связано с else:
var
i, y, j, k : integer;
begin
// определение значений переменных i, y, j, k
if (i > y) and (j = 55) then
if k > y then
k := y
else // относиться к if k > y
y := k;
end;
С помощью комментария можно показывать к какому if относиться else. Это подсказка себе на будущее для компилятора она не имеет никакого значения. Писать вложенных друг в друга составные операторы следует с особой тщательностью, аккуратно, не допуская ошибок и неточностей.
Массив как тип данных, определение, назначение, структура. Объявление и программирование ввода-вывода одномерного, двух и многомерного массивов. Примеры применения в программах.
Массивом называется упорядоченная индексированная совокупность однотипных элементов, имеющих общее имя. Элементами массива могут быть данные различных типов, включая структурированные. Каждый элемент массива однозначно определяется именем массива и индексом (номером этого элемента в массиве) или индексами, если массив многомерный. Для обращения к отдельному элементу массива указываются имя этого массива и индекс (индексы) элемента, заключенный в квадратные скобки, например, arr1 [3, 35], arr1 [3] [35] или аrr3 [7].
Количество индексных позиций определяется размерностью массива (одномерный, двумерный и т. д.), при этом размерность не ограничивается. В математике аналогом одномерного массива является вектор, а двумерного— матрица. Индексы элементов массива должны принадлежать порядковому типу. Разные индексы одного и того же массива могут иметь различные типы. Чаще всего индекс имеет целочисленный тип.
Различают массивы статические и динамические.
Статический массив представляет собой массив, границы индексов и, соответственно, размеры которого задаются при объявлении, т. е. они известны еще до компиляции программы. Формат описания типа статического массива:
Определение типа статического массива
1. Array [Имя массива] of <Тип элементов>;
Например,
Определение типа статического массива
1. Type tm = Array[1 .. 10, 1 .. 100] of real;
...
Определение типа статического массива
1. var
2. arr1, arr1 : tm;
3. arr3 : Array[20 .. 100] of char;
4. arr4 : Array['a' .. 'z'] of integer;
Переменные arr1 и arr2 являются двумерными массивами по 1000 элементов (10 строк х 100 столбцов). Каждый элемент этих массивов представляет собой число типа real. Для объявления массивов arr1 и аrr2 введен специальный тип tm. Переменные аrrЗ и аrr4 являются одномерными массивами длиной в 81 символ и 26 целых чисел соответственно.
Динамический массив представляет собой массив, для которого при объявлении указывается только тип его элементов, а размер массива определяется при выполнении программы. Формат описания типа динамического массива:
Формат описания динамического массива
1. Array of <Тип элементов>;
Во время выполнения программы размер динамического массива задается процедурой SetLength(var S; NewLength: Integer), которая для динамического массива S устанавливает новый размер, равный NewLength. Выполнять операции с динамическим массивом и его элементами можно только после задания размеров этого массива.
После задания размера динамического массива для определения его длины, а также минимального и максимального номеров элементов используются функции Length(), Low() и High() соответственно. Нумерация элементов динамического массива начинается с нуля, поэтому функция Low() для него всегда возвращает значение 0.
Приведем пример использования динамического массива.