Ada (798525), страница 8
Текст из файла (страница 8)
Массивы (array)Понятие массива подразумевает один из механизмов структурирования данных и являетсяодним из способов построения составных типов данных. В сущности, массив - это наборданных идентичного типа. Как правило, массиву дается какое-то имя, которое будет обозначатьвесь набор данных, и механизм индексации, позволяющий обращаться к индивидуальнымэлементам набора. На сегодняшний день, большинство языков программированияпредусматривают возможность работы с различного типа массивами.Ада предоставляет массивы подобно языку Паскаль, и, при этом, добавляет некоторые новыеполезные особенности. Неограниченные и динамические массивы, атрибуты массивов - вотнекоторые из предлагаемых расширений.4.1 Простые массивы4.1.1 Описание простого массиваВ общем случае, при объявлении массива, сначала производится описание соответствующеготипа.
Затем, экземпляр массива может быть создан используя описание этого типа.type Stack is array (1..50) of Integer;Calculator_Workspace : Stack;type Stock_Level is Integer range 0..20_000;type Pet is (Dog, Budgie, Rabbit);type Pet_Stock is array(Pet) of Stock_Level;Store_1_Stock : Pet_Stock;Store_2_Stock : Pet_Stock;В приведенном выше примере, тип Stack - это массив из 50-ти целочисленных элементов типаInteger, а Calculator_Workspace - это переменная типа Stack. Еще одним описаниеммассива является тип Pet_Stock.
При этом, тип Pet_Stock - это массив элементов типаStock_Level, а для индексирования элементов массива Stock_Level используетсяперечислимый тип Pet. Переменные Store_1_Stock и Store_2_Stock - это переменныетипа Pet_Stock.Общая форма описания массива имеет следующий вид:type <имя_массива> is array (<спецификация_индекса>) of <тип_элементов_массива>;Необходимо заметить:•••спецификация индекса может быть типом (например, Pet)спецификация индекса может быть диапазоном (например, 1..50)значения индекса должны быть дискретного типа4.1.2 Анонимные массивыМассив может быть объявлен непосредственно, без использования предопределенного типа:No_Of_Desks : array(1..No_Of_Divisions) of Integer;В этом случае массив будет называться анонимным (поскольку он не имеет явного типа) и онбудет несовместим с другими массивами - даже такими, которые описаны таким же самымобразом.
Кроме того, такие массивы не могут быть использованы как параметры подпрограмм.В общем случае рекомендуется избегать использования анонимных массивов.4.1.3 Организация доступа к отдельным элементам массиваОрганизацию доступа к отдельным элементам массива проще всего продемонстрировать напростых примерах. Так для обращения к значению элемента массива Store_1_Stock,описанного ранее, можно использовать:if Store_1_Stock(Dog) > 10 then ...В приведенном примере производится чтение значения элемента массива Store_1_Stock(доступ по чтению).Для сохранения значения в элементе массива Store_2_Stock (доступ по записи) можноиспользовать:Store_2_Stock(Rabbit) := 200;Необходимо отметить, что в обоих случаях доступ к элементу массива в Аде внешне никак неотличается от вызова функции.4.1.4 Агрегаты для массивовВ общем случае, агрегат массива - это совокупность значений для каждого элемента массива.Использование агрегатов позволяет выполнять одновременное присваивание значений всемэлементам массива в эффективной и элегантной форме.Рассмотрим следующий пример:Store_1_Stock := (5, 4, 300);В данном случае, присваивание значений элементам массива Store_1_Stock выполняется спомощью агрегата.
Следует учесть, что в этом примере значения в агрегате присваиваются впорядке соответствующем следованию элементов в массиве. Такая нотация называетсяпозиционной или неименованой, а такой агрегат - позиционный или неименованый агрегат.Кроме позиционной нотации, возможно использование именованой нотации. В этом случаеименуется каждый индивидуальный элемент массива. Используя именованую нотацию,предыдущий пример можно переписать следующим образом:Store_1_Stock := (Dog => 5, Budgie => 4, Rabbit => 300);Такой вид агрегата называют именованым агрегатом.Приведем еще один пример именованого агрегата:Store_1_Stock := (Dog | Budgie => 0, Rabbit => 100);В пределах одного агрегата, Ада допускает использовать только один вид нотации.
Это означает,что комбинирование позиционной и именованой нотации в одном агрегате - не допустимо ибудет вызывать ошибку компиляции. Например:Store_1_Stock := (5, 4, Rabbit => 300);-- это недопустимо!В агрегате может указываться диапазон дискретных значений:Store_1_Stock := (Dog..Rabbit => 0);Агрегаты обоих видов удобно использовать в описаниях:Store_1_Stock:Pet_Stock := (5, 4, 300);С агрегатами массивов разрешается использование опции others, которая практически полезнапри установке всех элементов массива в какое-либо предопределенное значение. Стоит учесть,что в таких случаях часто требуется квалификация типа.New_Shop_Stock: Pet_Stock := (others := 0);Рассмотрим следующие описания:declaretype Numbers1 is array(1..10) of Integer;type Numbers2 is array(1..20) of Integer;A : Numbers1;B : Numbers2;beginA := (1, 2, 3, 4, others => 5);end;Заметьте, что в данном случае опция others используется вместе с позиционной нотацией.Поэтому Ада потребует указать квалификацию типа:A : = Numbers1'(1, 2, 3, 4, others => 5);В общем случае, при использовании опции others совместно с любой из двух нотаций,позиционной или именованой, требуется указывать квалификацию типа.4.1.5 Отрезки (array slices)Для одномерных массивов Ада предусматривает удобную возможность указания несколькихпоследовательных компонент массива.
Такая последовательность компонент массива называетсяотрезком массива (array slice). В общем случае, отрезок массива может быть задан следующимобразом:<имя_массива> (<диапазон_значений_индекса>)Таким образом, для переменной Calculator_Workspace типа Stack, рассмотренных ранее,можно указать отрезок, содержащий элементы с 5-го по 10-й, следующим образом:Calculator_Workspace (5 .. 10) := (5, 6, 7, 8, 9, 10);ВданномпримеревыполняетсяприсваиваниезначенийэлементаммассиваCalculator_Workspace, которые попадают в указанный отрезок, с использованиемпозиционного агрегата массива.Приведем еще один простой пример:Calculator_Workspace (25 .. 30) := Calculator_Workspace (5 ..
10);Напомним что использование отрезков допускается только для одномерных массивов.4.1.6 Массивы-константыАда допускает использование массивов-констант. В таких случаях, при описании массиваконстанты, необходимо инициализировать значения всех его элементов. Такая инициализация,как правило, осуществляется с помощью агрегатов массивов. Например:type Months is (Jan, Feb, Mar, .... , Dec);subtype Month_Days is Integer range 1..31;type Month_Length is array (Jan..Dec) of Month_Days;Days_In_Month : constant Month_Length := (31, 28, 31, 30, ... , 31);4.1.7 Атрибуты массивовС массивами ассоциируются следующие атрибуты:<имя_массива>'First<имя_массива>'Last-- нижняя граница массива-- верхняя граница массива<имя_массива>'Length-- количество элементов в массиве-- <имя_массива>'Last - <имя_массива>'First + 1<имя_массива>'Range-- подтип объявленный как-- <имя_массива>'First..<имя_массива>'LastЭти средства очень полезны для организации перебора элементов массивов.for Count in <имя_массива>'Range loop...end loopВ приведенном выше примере, каждый элемент массива будет гарантированно обработан.4.2 Многомерные массивыАда позволяет использовать многомерные массивы.
В качестве простого примера многомерногомассива рассмотрим двухмерный массив целых чисел Square:Square_Size : constant := 5;subtype Square_Index is Integer range 1..Square_Size;type Square is array (Square_Index, Square_Index) of Integer;Square_Var: Square := ( others => (others => 0) );Здесь, агрегат, который инициализирует переменную Square_Var типа Square в нуль,построен как агрегат массива массивов, поэтому требуется двойное использование скобок(опции others использованы для упрощения примера).Более сложный пример инициализации этой переменной, использующий агрегат с позиционнойнотацией, может иметь следующий вид:----------------- столбцыSquare_Var1: Square := ( ( 1,( 6, 7, 8, 9, 10),23452,3,4,5),-- строка 1-- строка 2(11, 12, 13, 14, 15),-- строка 3(16, 17, 18, 19, 20),-- строка 4(21, 22, 23, 24, 25) );-- строка 5Доступ к элементам такого массива можно организовать следующим образом:Square_Var(1, 5) := 5;Square_Var(5, 5) := 25;Возможно использование альтернативного способа для описания подобного двумерногомассива.
Его можно описать как массив рядов (иначе - строк), где каждый ряд являетсяодномерным массивом целых чисел Square_Row.Square_Size : constant := 5;subtype Square_Index is Integer range 1..Square_Size;typetypeSquare_Row is array (Square_Index) of Integer;Squareis array (Square_Index) of Square_Row;Square_Var: Square := ( others => (others => 0) );Примечательно, что инициализация переменных в обоих вариантах реализации двумерногомассива выполняется одинаково.В этом случае, доступ к элементам массива можно организовать следующим образом:Square_Var (1)(5) := 5;Square_Var (5)(5) := 25;С многомерными массивами можно использовать те же атрибуты, которые допустимы дляпростых одномерных массивов. При этом несколько изменяется форма указания атрибутов:<имя_массива>'First(N)<имя_массива>'Last(N)<имя_массива>'Length(N)<имя_массива>'Range(N)В данном случае, значение определяемое, например, как <имя_массива>'Range(N) будетвозвращать диапазон N-мерного индекса.4.3 Типы неограниченных массивов (unconstrained array),предопределенный тип StringДо настоящего момента мы рассматривали только такие массивы у которых диапазон значенийиндекса был заведомо известен.
Такие массивы называют ограниченными массивами, и онимогут быть использованы для создания экземпляров объектов с четко определенными во времяописания типа границами.В дополнение к таким типам, Ада позволяет описывать типы массивов, которые не имеют четкоопределенного диапазона для индексных значений, когда описание типа не определяет границмассива.
Поэтому такие массивы называют неограниченными массивами (unconstrained array).Типы неограниченных массивов позволяют описывать массивы, которые во всех отношенияхидентичны обычным массивам, за исключением того, что их размер не указан. Ограничениемассива (указание диапазона для индексных значений) производится при создании экземпляраобъекта такого типа.Таким образом, описание неограниченого массива предоставляет целый класс массивов,которые содержат элементы одинакового типа, имеют одинаковый тип индекса и одинаковоеколичество индексов, но при этом разные экземпляры объеков такого типа будут иметь разныеразмеры.Этот механизм удобно использовать в случаях когда массив произвольного размера необходимопередать в подпрограмму как параметр.Примером описания неограниченного массива целых чисел может служить следующее:typeNumbers_Arrayis array (Positive range <>) of Integer;Символы "<>" указывают, что диапазон значений индекса должен быть указан при описанииобъектов типа Numbers_Array.