Файл: Учебное пособие для студентов Авторы А. Н. Вальвачев, К. А. Сурков, Д. А. Сурков, Ю. М. Четырько Содержание Содержание 1.doc

ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 04.05.2024

Просмотров: 144

Скачиваний: 4

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.


Массивы в целом участвуют только в операциях присваивания. При этом все элементы одного массива копируются в другой. Например, если объявлены два массива A и B,

var

A, B: array[1..10] of Integer;

то допустим следующий оператор:

A := B;

Оба массива-операнда в левой и правой части оператора присваивания должны быть не просто идентичны по структуре, а описаны с одним и тем же типом, иначе компилятор сообщит об ошибке. Именно поэтому все массивы рекомендуется описывать в секции type.

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

program Console;
{$APPTYPE CONSOLE}
uses

SysUtils;
var

A: array[1..5] of Double;

Sum: Double;

I: Integer;
begin

for I := 1 to 5 do Readln(A[I]);

Sum := 0;

for I := 1 to 5 do Sum := Sum + A[I];

Writeln(Sum);

Writeln('Press Enter to exit...');

Readln;

end.

Для массивов определены две встроенные функции — Low и High. Они получают в качестве своего аргумента имя массива. Функция Low возвращает нижнюю, а High — верхнюю границу этого массива. Например, Low(A) вернет значение 1, а High(A) — 5. Функции Low и High чаще всего используются для указания начального и конечного значений в операторе цикла for. Поэтому вычисление суммы элементов массива A лучше переписать так:

for I := Low(A) to High(A) do Sum := Sum + A[I];

В операциях с многомерными массивами циклы for вкладываются друг в друга. Например, для инициализации элементов таблицы, объявленной как

var

Table: array[1..5, 1..20] of Double;

требуются два вложенных цикла for и две целые переменные Col и Row для параметров этих циклов:

for Col := 1 to 5 do

for Row := 1 to 20 do

Table[Col, Row] := 0;

2.11.3. Массивы в параметрах процедур и функций

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

const

Max = 63;

type

TStatistics = array [0..Max] of Double;
function Average(const A: TStatistics): Double;

var

I: Integer;

begin

Result := 0;

for I := Low(A) to High(A) do Result := Result + A[I];

Result := Result / (High(A) - Low(A) + 1);

end;

Функция Average принимает в качестве параметра массив известной размерности. Требование фиксированного размера для массива-параметра часто является чрезмерно сдерживающим фактором. Процедура для нахождения среднего значения должна быть способна работать с массивами произвольной длины. Для этой цели в язык Delphi введены открытые массивы-параметры. Такие массивы были заимствованы разработчиками языка Delphi из языка Modula-2. Открытый массив-параметр описывается с помощью словосочетания
array of, при этом границы массива опускаются:

function Average(const A: array of Double): Double;

var

I: Integer;

begin

Result := 0;

for I := Low(A) to High(A) do Result := Result + A[I];

Result := Result / (High(A) - Low(A) + 1);

end;

Внутри подпрограммы Average нижняя граница открытого массива A равна нулю (Low(A) = 0), а вот значение верхней границы (High(A)) неизвестно и выясняется только на этапе выполнения программы.

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

Вот пример использования функции Average:

var

Statistics: array[1..10] of Double;

Mean: Double;

begin

...

Mean := Average(Statistics);

Mean := Average([0, Random, 1]);

...

end;

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

И еще одно важное замечание по поводу открытых массивов. Некоторые библиотечные подпрограммы языка Delphi принимают параметры типа array of constоткрытые массивы констант. Массив, передаваемый в качестве такого параметра, обязательно конструируется в момент вызова подпрограммы и может состоять из элементов различных типов (!). Физически он состоит из записей типа TVarRec, кодирующих тип и значение элементов массива (записи рассматриваются ниже). Открытый массив констант позволяет эмулировать подпрограммы с переменным количеством разнотипных параметров и используется, например, в функции Format для форматирования строки (см. выше).

2.11.4. Уплотнение структурных данных в памяти

С целью экономии памяти, занимаемой массивами и другими структурными данными, вы можете предварять описание типа зарезервированным словом packed, например:

var

A: packed array[1..10] of Byte;

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


Заметим, что ключевое слово packed применимо к любому структурному типу данных, т.е. массиву, множеству, записи, файлу, классу, ссылке на класс.

2.12. Множества

2.12.1. Объявление множества

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

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

type

TLetters = set of 'A'..'Z';

Теперь можно объявить переменную множественного типа:

var

Letters: TLetters;

Можно объявить множество и без предварительного описания типа:

var

Symbols: set of Char;

В выражениях значения элементов множества указываются в квадратных скобках: [2, 3, 5, 7], [1..9], ['A', 'B', 'C']. Если множество не имеет элементов, оно называется пустым и обозначается как [ ]. Пример инициализации множеств:

const

Vowels: TLetters = ['A', 'E', 'I', 'O', 'U'];

begin

Letters := ['A', 'B', 'C'];

Symbols := [ ]; { пустое множество }

end;

Количество элементов множества называется мощностью. Мощность множества в языке Delphi не может превышать 256.

2.12.2. Операции над множествами

При работе с множествами допускается использование операций отношения (=, <>, >=, <=), объединения, пересечения, разности множеств и операции in.

Операции сравнения (=, <>). Два множества считаются равными, если они состоят из одних и тех же элементов. Порядок следования элементов в сравниваемых множествах значения не имеет. Два множества A и B считаются не равными, если они отличаются по мощности или по значению хотя бы одного элемента.

Выражение

Результат

[1, 2] <> [1, 2, 3]

True

[1, 2] = [1, 2, 2]

True

[1, 2, 3] = [3, 2, 1]

True

[1, 2, 3] = [1..3]

True

Операции принадлежности (>=, <=). Выражение A >= B равно True, если все элементы множества B содержатся в множестве A. Выражение A <= B равно True, если выполняется обратное условие, т.е. все элементы множества A содержатся в множестве B.


Выражение

Результат

[1, 2] <= [1, 2, 3]

True

[1, 2, 3] >= [1, 2]

True

[1, 2] <= [1, 3]

False

Операция in. Используется для проверки принадлежности элемента указанному множеству. Обычно применяется в условных операторах.

Выражение

Результат

5 in [1..9]

True

5 in [1..4, 6..9]

False

Операция in позволяет эффективно и наглядно выполнять сложные проверки условий, заменяя иногда десятки других операций. Например, оператор

if (X = 1) or (X = 2) or (X = 3) or (X = 5) or (X = 7) then

можно заменить более коротким:

if X in [1..3, 5, 7] then

Операцию in иногда пытаются записать с отрицанием: X not in S. Такая запись является ошибочной, так как две операции следуют подряд. Правильная запись имеет вид: not (X in S).

Объединение множеств (+). Объединением двух множеств является третье множество, содержащее элементы обоих множеств.

Выражение

Результат

[ ] + [1, 2]

[1, 2]

[1, 2] + [2, 3, 4]

[1, 2, 3, 4]

Пересечение множеств (*). Пересечение двух множеств — это третье множество, которое содержит элементы, входящие одновременно в оба множества.

Выражение

Результат

[ ] * [1, 2]

[ ]

[1, 2] * [2, 3, 4]

[2]

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

Выражение

Результат

[1, 2, 3] – [2, 3]

[1]

[1, 2, 3] – [ ]

[1, 2, 3]

В язык Delphi введены две стандартные процедуры Include и Exclude, которые предназначены для работы с множествами.

Процедура Include(S, I) включает в множество S элемент I. Она дублирует операцию + (плюс) с той лишь разницей, что при каждом обращении включает только один элемент и делает это более эффективно.


Процедура Exclude(S, I) исключает из множества S элемент I. Она дублирует операцию – (минус) с той лишь разницей, что при каждом обращении исключает только один элемент и делает это более эффективно.

Выражение

Результат

S := [1, 3];

[1, 3]

Include(S, 2);

[1, 2, 3]

Exclude(S, 3)

[1, 2]

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

2.13. Записи

2.13.1. Объявление записи

Запись — это составной тип данных, состоящий из фиксированного числа элементов одного или нескольких типов. Описание типа записи начинается словом record и заканчивается словом end. Между ними заключен список элементов, называемых полями, с указанием идентификаторов полей и типа каждого поля:

type

TPerson = record

FirstName: string[20]; // имя

LastName: string[20]; // фамилия

BirthYear: Integer; // год рождения

end;

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

Чтобы получить в программе реальную запись, нужно создать переменную соответствующего типа:

var

Friend: TPerson;

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

Доступ к содержимому записи осуществляется посредством идентификаторов переменной и поля, разделенных точкой. Такая комбинация называется составным именем. Например, чтобы получить доступ к полям записи Friend, нужно записать:

Friend.FirstName := 'Alexander';

Friend.LastName := 'Ivanov';

Friend.BirthYear := 1991;

Обращение к полям записи имеет несколько громоздкий вид, что особенно неудобно при использовании мнемонических идентификаторов длиной более 5 символов. Для решения этой проблемы в языке Delphi предназначен оператор with, который имеет формат:

with <запись> do

<оператор>;

Однажды указав имя записи в операторе with, можно работать с именами ее полей как с обычными переменными, т.е. без указания идентификатора записи перед идентификатором поля: