Массивы определение описание размещение в памяти использование работа с массивами delphi

Обновлено: 03.07.2024

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

По признаку размещения в памяти массивы подразделяются на статические (static) и динамические (dynamic).

Статические массивы. Эти массивы объявляются с помощью такого формата:

array [indexType 1 , . indexType n ] of baseType

Каждый из типов indexType должен быть порядкового типа, диапазон которого не должен превосходить 2 Гбайт.

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

Многомерные массивы являются массивами массивов, вследствие чего описание type TMatrix = array[1..10] of array[1..50] of Real; эквивалентно type TMatrix = array[1..10, 1..50] of Real. Подобным образом, переменная MyMatrix типа TMatrix может индексироваться как MyMatrix[2,45] или MyMatrix[2][45].

Стандартные функции Low и High возвращают для типа массив или переменной­ низшую и высшую границу для первого индекса массива. Функция Length возвращает число элементов массива в первой размерности. Например, для массива array [-5..5] функция Low вернет –5, а Length вернет значение 11.

Одномерный, статический, упакованный массив символов (Char) называется упакованной строкой (packed string). Упакованные строки совместимы с другими строковыми типами и упакованными строками, которые имеют то же число элементов. Тип массива array[0..x] of Char называется массивом символов с отсчетом от нуля (zero-based character array), используется для хранения строк с завершающим нулем и совместим со значениями типа PChar.

Пример для массивов символов:

cArr : array [0..1000] of char;

// cArr:=sAnsi; несовместимость типов

// cArr:=sShort; несовместимость типов

// cArr:=PChar(sAnsi); несовместимость типов

// cArr:=PChar(sShort); недопустимое приведение типа

cArr:='array [0..1000] of char';

// sShort:=cArr; несовместимость типов

Динамические массивы. Эти массивы, впервые введенные в Delphi 4, не имеют фиксированного размера или длины. Память для них перераспределяется с помощью процедуры SetLength. Динамические массивы объявляются с использованием формата array of baseType, например

var MyFlexibleArray: array of Real;

При описании массива память для него не выделяется, но ее можно выделить так: SetLength(MyFlexibleArray, 20). Динамический массив всегда индексируется целочисленным типом и всегда с нуля, так что после приведенного примера первым элементом массива является MyFlexibleArray[0], а последним – MyFlexibleArray[19].

Попросту говоря, динамические массивы являются указателями, которые, подобно указателям на длинные строки PChar, могут индексироваться. Для освобождения памяти, выделенной массиву, просто присвойте его имени значение nil или вызовите процедуру Finalize.

Для динамических массивов нельзя применять операцию разыменования (^) или вызывать процедуры New и Dispose.

Если X и Y являются переменными одного типа динамический массив, оператор X := Yустанавливает для массива Х такую же длину, как и для массива Y, однако, в отличие от строк и статических массивов, не копирует элементы массива. Например, после выполнения кода

A, B: array of Integer;

значением элемента массива A[0] будет 2.

Присваивание значения элементу массива, например, MyFlexibleArray[2] := 7, не вызывает перераспределения памяти. Выход индекса за границу массива не контролируется на этапе компиляции программы, как сказано в документации к Delphi 5.0. На практике, по крайней мере в Delphi 6.0, выход индекса за границу массива контролируется на этапе выполнения программы, что весьма ценно.

При сравнении массивов сравниваются указатели, но не их содержимое.

Для усечения динамического массива можно использовать функцию Copy:

Function Copy(Vec; Index, Count: Integer): array;

Например, после выполнения оператора A := Copy(A, 5, 2) массив A будет содержать только два элемента.

К динамическим массивам можно применять также стандартные функции Length, High и Low. Length возвращает число элементов массива, High – наибольший индекс (Length–1), а Low –0. В случае массива нулевой длины High вернет –1.

Замечание. Описание формального параметра подпрограммы также может иметь вид array of baseType. Такие параметры называют открытыми массивами и никакого прямого отношения к динамическим массивам они не имеют.

Многомерные динамические массивы (multidimensional dynamic arrays).Для их объявления итеративно используется конструкция array of . . Например, описание

type TMessageGrid = array of array of string;

var Msgs: TMessageGrid;

вводит двумерный массив строк. Для инициализации такого массива вызывается процедура SetLength с двумя целочисленными параметрами. После этого выражение Msgs[0,0] указывает на первый элемент такого массива.

Можно создавать такие многомерные динамические массивы, которые не являются прямоугольными. Для этого при первом вызове SetLength ей передается число элементов по первой размерности, например:

var Ints: array of array of Integer;

Этот код выделяет память для 10 строк, но не для столбцов. Далее можно выделить для каждой строки любое число столбцов, например, SetLength(Ints[2], 5). Теперь уже можно присваивать значения элементам третьей строки (индекс 2), даже если для столбцов остальных строк память еще не была выделена. Следующий пример иллюстрирует создание треугольной матрицы:

A : array of array of integer;

for I := Low(A) to High(A) do

for J := Low(A[I]) to High(A[I]) do

A[I,J] := (I+1)*10 + J + 1;

Пример повторного применения процедуры SetLength и использования трехмерного динамического массива:

Во втором занятии мы рассмотрели несколько типов переменных: char, string, integer и double. Для решения простых задач этого уже достаточно. Но на практике требуется значительно большее разнообразие типов переменных.

Рассмотрим ещё один тип данных — массив. Собственно, в delphi 7 массив это даже не отдельный тип данных, а просто способ хранения некоторого количества данных одного типа.

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

Элементы массива пронумерованы. Эти номера называются индексом элемента. Если, например, имя массива будет vArr и массив хранит 10 элементов, то обращение к восьмому элементу будет иметь вид: vArr[7].

Как происходит обращение к элементу массива? Мы сказали, что адрес первого байта массива хранится в переменной массива. Если, например, массив хранит элементы целого типа integer, то под каждый элемент отводится 4 байта.

Почему индекс равен 7, а не 8? Это происходит из-за того, что первый элемент массива всегда имеет номер 0.

Очевидно, что для массива мощностью 10 элементов допустимые номера индекса от 0 до 9.

Если ввести другое значение индекса, то компилятор Delphi выдаст ошибку.

Посмотрим, как вычисляется адрес элемента массива с номером i.

Если адрес первого байта массива равен n, то адрес элемента с индексом i будет равен n+i*4. При i:=0 мы попадаем в начала массива, при i:=1 сдвигаемся на 4 байта и попадаем в начало первого элемента, и так далее.

Типы массивов в delphi

Не во всех языках программирования строго требуется, чтобы все элементы массива были одного типа.

Поэтому особо подчёркивается, что в delphi массивы являются «типизированными». В ряде случаев нетипизированные массивы более удобны и позволяют решать задачу более элегантно. Но одновременно они наряду с дополнительными удобствами привносит и свои трудности. Нетипизированные массивы могут быть источниками трудно определяемых ошибок.

Массивы подразделяют на одномерные и многомерные.

Например, для хранения данных из таблицы применяют в delphi двумерный массив. Обращение к элементу двумерного массива будет выглядеть, например, следующим образом: vArr[2,7].

Или в общем виде vArr[i,j]. Индекс i ассоциируют с номером столбца, а j — с номером строки.

Аналогично определяются массивы трёх и более измерений.

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

Надо ли Вам будет использовать динамические массивы — Вы решите сами по мере усложнения поставленных задач.

Элементы массива целого типа

Значения, хранящиеся в массиве, называются элементами массива.

Рассмотрим пример. Пусть нам надо хранить десять целых чисел. Можно поступить так: объявить десять переменных типа Integer. А если их сто, тысяча, миллион?

Имеется более элегантная возможность. Значения располагают в памяти одно за другим. Запоминают адрес первого числа, а потом указывают, на каком месте последовательности стоит то число, которое надо прочитать.

В терминах delphi это выглядит так. Объявляется тип данных array с помощью ключевого слова type :

Далее объявляется переменная типа TArray следующим образом:

Можно объявить переменную-массив и обычным образом:

Однако первый способ предпочтительнее.

Объявляя переменную «massiv» типа array, мы тем самым декларировали, что будем хранить цепочку из пятнадцати целых чисел.

Выше мы говорили, что обратится к конкретному элементу массива можно по его индексу.

Например, если «у» является переменной целого типа, то справедливо выражение:

Обмен данными между массивами

Обменяться данными между переменными очень просто. Достаточно поставить оператор равенства между переменными. Например, x:=y; (оператор равенства — выражение «:=»).

Так же можно поступить и с массивами, но при соблюдении определённых условий. Если мы объявим массив одним из двух способов:

Индекс массива

Мы уже использовали в качестве индекса массива целые числа.

Но в качестве индекса можно использовать переменную целого типа. Это исключительно удобно при обработке массива в цикле.

Пример программы работы с массивом

В качестве примера работы с массивом часто решают следующую задачу.

Пусть есть массив целых, например чётных, чисел. Надо вычислить сумму всех элементов этого массива. Предположим, что мощность массива четыре элемента.

Начнём с самого примитивного варианта.

Обратите внимание, что имя типа, как и имя переменной, программист назначает произвольно (какие символы можно использовать в идентификаторах переменных смотри в справочной литературе!).

Объявим переменные и заполним значениями элементы массива.

Далее вычислим сумму значений, хранящихся в массиве.

Но, с расчётом на будущее, лучше вычисление суммы представить в виде следующего алгоритма:

Вычисление суммы происходит следующим образом.

Берётся значение переменной sum, к нему прибавляется значение из ar[2], результат записывается в sum, затирая старое значение. Таким образом на втором шаге мы получаем сумму значений из первого и второго элементов массива. И так далее.

Выше мы говорили, что в качестве индекса можно использовать переменную целого типа. Используя этот факт, приведём классическое решение.

Мы уже неоднократно применяли один из операторов — оператор присваивания «:=» Теперь рассмотрим ещё один оператор — оператор цикла for. Напишем код и рассмотрим, как работает оператор for.

Предварительно введём вспомогательную переменную целого типа:

Оператор for организует цикл, который повторяется заданное число раз.

Начиная своё выполнение, оператор for проверяет значение переменной i.

В нашем примере её начальное значение равно «1» . А в принципе оно может быть задано любым числом.

Также и нижняя граница цикла может быть целочисленной переменной.

Например, i:=n, где n – целочисленная переменная.

Если значение i меньше значения, указанного после ключевого слова to (в нашем случае это 4), то начинается выполняться тело цикла.

Выполнив все строки кода и дойдя до оператора end, управление передаётся оператору for и он увеличит переменную цикла i на единицу.

Потом сравнит её со значением, указанным после to. Если i меньше этого значения, то вновь выполнится тело цикла.

И так до тех пор, пока i не станет больше значения, стоящего после to. Тогда тело цикла больше выполняться не будет, а управление перейдет к выражению, записанному после оператора end; .

Теперь, когда все части решения задачи у нас в руках, продолжим её разработку.

Напишем тело цикла, выполняющего решение поставленной задачи.

Здесь i, пробегая значения от 1 до 4, записывает в элементы массива чётные значения. В итоге будет сформирован массив, элементы которого будут содержать чётные целые числа.

Теперь вычислим суммы всех элементов массива. Запишем:

Замечание. Всё, что написано после «//», является комментарием и не воспринимается delphi как код.

Обратите внимание на очень простое, но очень нужное выражение: sum:=0;

Этим выражение мы задаём начальное значение переменной!

Дело в том, что объявляя переменную, delphi не задаёт её какого-либо начального значения. Поэтому пока мы явно не присвоим ей значения, в ней может содержаться всё, что угодно!


Массив— это структура данных, представляющая собой набор переменных одинакового типа, имеющих общее имя. Массивы удобно использовать для хранения однородной по своей природе информации, например, таблиц и списков.

Хочешь 106 видеоуроков по Delphi в которых я разжевал подробнейшим образом все тонкости программирования на этом языке?

Тогда тебе нужно кликнуть сюда:

ЗАКАЗАТЬ

Массивы в Delphi

Объявление массива

Массив, как и любая переменная программы, перед использованием должен быть объявлен в разделе объявления переменных. В общем виде инструкция объявления массива выгладит следующим образом:

  • имя — имя массива;
  • array — зарезервированное слово языка Delphi, обозначающее, что объявляемое имя является именем массива;
  • нижний_индекс и верхний_индекс — целые константы, определяющие диапазон изменения индекса элементов массива и, неявно, количество элементов (размер) массива;
  • тип — тип элементов массива.

Примеры объявления массивов:

temper:array[ 1..31 ] of real ;

koef: array [ 0..2 ] of integer ;
name: array [ 1..30 ] of string [ 25 ];

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

Если Вам понравился видеоурок - то обязательно получите остальные видеоуроки - скачать.

При объявлении массива удобно использовать именованные константы. Именованная константа объявляется в разделе объявления констант, который обычно располагают перед разделом объявления переменных. Начинается раздел объявления констант словом const. В инструкции объявления именованной константы указывают имя константы и ее значение, которое отделяется от имени символом "равно". Например, чтобы объявить именованную константу нв, значение которой равно 10, в раздел const надо записать инструкцию: нв=ю. После объявления именованной константы ее можно использовать в программе как обычную числовую или символьную константу. Ниже в качестве примера приведено объявление массива названий команд-участниц чемпионата по футболу, в котором используются именованные константы.


const
ВТ = 15; // число команд
SN = 25 ; // предельная длина названия команды
var
team: array [ 1.. BT] of string [SN];

Для того чтобы в программе использовать элемент массива, надо указать имя массива и номер элемента (индекс), заключив индекс в квадратные скобки. В качестве индекса можно использовать константу или выражение целого типа, например:

team[ 1 ] := 'Зенит 1 ;

d := koef[l]*koef[l]- 4 *koef[ 2 ]*koef[ 1 ];
ShowMessage(name[n+ 1 ]);
temper := StrToFloat(Editl . text);

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

Имя: array [нижний_индекс. .верхний_индекс] of тип = (список) ;

где список — разделенные запятыми значения элементов массива.

a: array[lO] of integer = ( 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
Team: array [ 1..5 ] of String[ 10 ]=( 'Зенит' , 'Динамо' , 'Спартак' , 'Ротор' , 'СКА' );

for i := 1 to 10 do a:= 0 ;

Типичными операциями при работе с массивами являются:

  • вывод массива;
  • ввод массива;
  • поиск максимального или минимального элемента массива;
  • поиск заданного элемента массива;
  • сортировка массива.

Вывод массива

Под выводом массива понимается вывод на экран монитора (в диалоговое окно) значений элементов массива.

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

В качестве примера на рис. 5.1 приведено диалоговое окно приложения, которое демонстрирует инициализацию и процесс вывода значений элементов массива в поле метки. Программа выводит пронумерованный список футбольных команд. Следует обратить внимание, что для того чтобы список команд выглядел действительно как список, свойству Label1.AutoSize нужно присвоить значение False (присвойте свойству Label1.Autosize значение True и посмотрите, как будет работать программа). Текст программы приведен в листинге.


Листинг. Инициализация и вывод массива


Ввод массива

Под вводом массива понимается процесс получения от пользователя (или из файла) во время работы программы значений элементов массива, "Лобовое" решение задачи ввода элементов массива — для каждого элемента массива создать поле ввода. Однако если требуется ввести достаточно большой массив, то такое решение неприемлемо. Представьте форму, например, с десятью полями редактирования! Очевидно, что последовательность чисел удобно вводить в строку таблицы, где каждое число находится в отдельной ячейке. Ниже рассматриваются два варианта организации ввода массива с использованием компонентов StringGrid И Memo.

Под вводом массива понимается процесс получения от пользователя (или изфайла) во время работы программы значений элементов массива,"Лобовое" решение задачи ввода элементов массива — для каждого элемента массива создать поле ввода. Однако если требуется ввести достаточно большой массив, то такое решение неприемлемо. Представьте форму, например,с десятью полями редактирования! Очевидно, что последовательность чисел удобно вводить в строку таблицы,где каждое число находится в отдельной ячейке. Ниже рассматриваются два варианта организации ввода массива с использованием компонентов StringGrid И Memo.

Использование компонента StringGrid

Для ввода массива удобно использовать компонент StringGrid. Значок компонента StringGrid находится на вкладке Additional (рис. 5.2).

Массивы в Delphi

Компонент strinqGrid представляет собой таблицу, ячейки которой содержат строки символов.

В качестве примера использования компонента stringGrid для ввода массива рассмотрим программу, которая вычисляет среднее арифметическое значение элементов массива. Диалоговое окно программы приведено на рис. 5.3. Компонент stringGrid используется для ввода массива, компоненты Label1 и Label2 — для вывода пояснительного текста и результата расчета, Buttoni — для запуска процесса расчета.


Добавляется компонент stringGrid в форму точно так же, как и другие компоненты. После добавления компонента к форме нужно выполнить его настройку в соответствии с табл. 5.2. Значения свойств Height и width следует при помощи мыши установить такими, чтобы размер компонента был равен размеру строки.

Текст программы приведен в листинге.

Значения свойств компонента StringGrid1

Свойство Значение
ColCount 5
FixedCols 0
RowCount 1
DefaultRowHeight 24
Height 24
DefaultColWidth 64
Width 328
Options.goEditing true
Options.AlwaysShowEditing true
Options.goTabs true

Листинг. Ввод и обработка массива целых чисел

2 type Name = array of Base type; // Динамический массив

Delphi имеет три основных типа массивов :

1. Статические массивы

Они определены установленными, неизменяемыми размерами. Они могут быть одномерными или многомерными - последний является массивом массивов (массивов и т.д). Размер и диапазон такого многомерного массива всегда даются для самого высокого, крайнего левого массива - родительского массива.

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

Index type, где Index целое число, обычно Byte или Word. Диапазон этого типа определяет диапазон измерения. Например, Byte дает дипазон 0..255.

Ordinal..Ordinal Альтернативно, диапазон каждого измерения может быть задан предписанными порядковыми значениями, типа 22..44.

2. Динамические массивы

Динамические массивы не имеют никакой предраспределенной памяти. Определяется только когда создан указатель. Размеры таких массивов должны быть установлены прежде, чем они будут использоваться. Например :

SetLength(dynArray, 5);

устанавливает размер одномерного массива dynArray в 5 элементов. При этом будет распределена память.

Все динамические массивы начинаются с индекса = 0.

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

3. Открытые массивы

И статические и динамические массивы можно передать подпрограммам как параметры. Если определение параметра массива не имеет никакого диапазона (то есть, динамический тип массива), то вы должны, как это ни парадоксально передавать статический массив как параметр. Такой массив упоминается как Открытый массив. Delphi передает длину как скрытый параметр для подпрограммы.

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

Читайте также: