2.4.2.2. Иерархические (вложенные) записи. Возможно существование записей, отдельные поля которых представляют собой также записи. Для того чтобы понять, как это реализуется, попробуем добавить в описание комбинированного типа Еmрlоуее пару полей-записей. Пусть это будут поля, содержащие информацию об адресе служащего (почтовый код, город, улица, дом, квартира) и его дате рождения (число, месяц, год). В принципе соответствующие поля (пять полей и три поля с данными соответственно об адресе и дате рождения) можно добавить непосредственно в описание комбинированного типа Еmрlоуее. А что если эту информацию впоследствии потребуется использовать в качестве полей еще в каких-нибудь комбинированных типах? Поэтому лучше для адреса и даты рождения создать самостоятельные комбинированные типы в разделе описаний программы, которые затем добавить как поля в тип Еmрlоуее. Описание этих типов может выглядеть так:

tуре

Address = rесоrd

РоstСоdе:; {Почтовый код}

City, Street:string[20]; {Город, улица}

House:word; {Дом}

Араrtment:word {Квартира}

end; {address}

Date = rесоrd

Dау:1..31; {Число}

Моnth:1..12; {Месяц}

Yеаr;1900..2000 {Год}

end; {date}

NеwЕmрlоуее = record

ID:word; {Идентификатор (личный номер)}

FirstName, SecondName, SurName : string[20];

{Имя, фамилия, отчество}

Standing: bytе; {Стаж}

Salary:rеаl {Зарплата}

BirthDate:date; {Дата рождения}

Habitation:address {Место жительства}

end;

vаr

NewAssistant: NеwЕmрlоуее;

Описанный выше комбинированный тип wЕmрlоуее включает восемь полей, два из которых – BirthDate (Дата рождения) и Habitation (Место жительства) – представляют собой записи, типы которых (Date и Address соответственно) объявлены перед описанием типа NеwЕmрlоуее. Структура комбинированного типа NеwЕmрlоуее представлена на рис.1.

НЕ нашли? Не то? Что вы ищете?

Рис.1. Тип NewEmployee

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

NеwЕmрlоуее. Аddress.РоstСоdе

или

NеwЕmрlоуее.Date.Dау

Если имеют место несколько уровней вложения записей, составные имена могут быть очень длинными. Однако ничто не мешает в этих случаях широко применять оператор WIТН.

2.4.2.3. Записи с вариантами. Иногда возникает необходимость, чтобы в зависимости от значения определенного поля записи структура этой записи частично изменялась. Например, одно из полей комбинированного типа Еmрlоуее, которое представляет собой вложенную запись, содержит информацию о месте жительства служащего. Однако городской адрес обычно выглядит не так, как загородный. Что если кто-либо из членов коллектива проживает за пределами города? Для решения этой проблемы Turbo Раsсаl позволяет в структуре комбинированного типа Аddress создать вариантную часть, в которой набор полей мог бы изменяться в соответствии с видом адреса. Итак, в структуре адреса необходима некоторая фиксированная часть – группа полей, присутствующих постоянно, независимо от характера адреса, и вариантная часть с изменяющимся набором полей. Фиксированная часть в нашем случае могла бы включать поля PostCode (почтовый код), Street (улица) и Ноusе (дом) – элементы, присутствующие в любом адресе. Вариантная часть записи для городского адреса могла бы включать поля City и Apartment (город и квартира), а для загородного адреса – поля Аrеа (область), District (район) и Community (населенный пункт). Для управления вариантной частью адреса введем в структуру комбинированного типа Address поле City_оr_Country (город/загород), для которого допустимы только значения City и Country. Вот как может выглядеть описание такого преобразованного комбинированного типа (присвоим ему имя NewAddress):

tуре

NewAddress = rесоrd

РоstСоdе:; {Почтовый код}

Street:string[20]; {Город, улица}

House:word; {Дом}

саsе City_оr_Country : City, Country оf

City:(City:string[20]; {Город}

Appartment:word); {Квартира}

Соuntrу :(Аrеа,District, {Область, район}

Community:string[20]); {Населенный пункт}

end; {NewAdress}

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

саsе City_оr_Countrу : City, Countrу оf

которая объявляет специальное поле Cityr_Countrу, способное принимать только два значения (Citу и Сountrу – т. е. принадлежит перечислимому типу). Это поле, которое называется полем признака (или селектором выбора – по аналогии с оператором САSЕ), определяет вариантную часть записи.

Строка, начинающая вариантную часть, включает зарезервированные слова CASE и OF, имеющие смысл вариант и из соответственно Дальше следует перечень меток, представляющих собой все допустимы значения поля признака (в нашем случае две метки – City и Country). После каждой метки (за двоеточием, в круглых скобках) представлен перечень полей для данного варианта, причем для каждого поля указывается тип. Завершение данной конструкции CASE-OF – перечень меток ключевым словом ЕND не предусмотрено. Правда, в конце описание комбинированного типа NewAddress слово ЕND все же имеется, однако оно здесь служит парой зарезервированному слову RECORD, а не CASE. Иначе говоря, то, что мы здесь видим, вовсе не представляет собой оператор CASE, а является всего лишь конструкцией, внешне похожей на оператор САSЕ, описывающей вариантную часть записи.

Структура комбинированного типа NewAddress представлена на рис.2.

При использовании записей с вариантами следует иметь в виду следующие особенности.

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

• Поле признака вариантной части не принадлежит ни к фиксированной, ни к вариантной частям и выносится в заголовок вариантной части.

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

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

• Объем памяти, выделяемый для записи, определяется суммой длин полей. Объем памяти для записи с вариантами определяется по самому объемному варианту.

Рис.2. Тип NewAddress

В созданном нами комбинированном типе wЕmрlоуее мирно сосуществуют вложенные записи (Date и NewAddress) и записи с вариантами. Собственно, вложенная запись NewAddress одновременно является записью с вариантами. Этот пример наглядно иллюстрирует, насколько сложные структуры данных можно создавать с использованием записей.

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

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

Действия над полями записи

Поскольку поле записи трактуется как переменная, оно может фигурировать в выражениях. (Как обратиться к полю записи, мы выяснили выше – для этого достаточно указать имя записи и имя поля.) Набор операций над полями записи соответствует операциям, допустимым для типа, которому принадлежит данное поле. Какие операции и подпрограммы применимы к тому или иному простому типу, мы уже знаем.

Действия над записями

Здесь, вероятно, уместно повторно упомянуть оператор WITH, который так и называется: оператор над записями.

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

х:=у;

В результате значения всех полей записи Х окажутся присвоены полям записи Y.

Однако нельзя использовать с записями операции сравнения. Неверно, например, было бы к записям Х и Y применить оператор

while х=у do...

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

Совершенно не применимы к записям (в целом) арифметические и логические операции.

Кроме того, следует особо подчеркнуть, что к записям (подобно массивам, но в отличие от строк) нельзя применять стандартные процедуры Read и Write. Однако можно организовать считывание или вывод на экран каждого поля записи в отдельности.

2.4.3. Множества. Подобно массиву, множество – это совокупность связанных дан­ных, состоящая из элементов одного типа, который называется базо­вым. Однако, в отличие от массива (в котором число элементов фикси­ровано), множество может включать произвольное число элементов.

Описание множественного типа:

Tуре

s=set of а

Здесь SЕТ и OF – зарезервированные слова, имеющие смысл мно­жество и из; S – имя объявляемого множественного типа; А – базовый тип множества.

Вот примеры описаний множественных типов и переменных, принадлежащих этим типам:

tуре

а1=set of 1..3;

а2=set of а..е;

а3=set of char;

r

х:а1; у:а2; z3;

В качестве базового для множественного типа А1 задан интервальный тип (1..3). Переменная X, принадлежащая множественному типу А1, может принимать значения [], [I], [2], [1,2], [3], [1,3], [2,3], [1,2,3] (всего 8 (2³) значений). Иными словами, значениями множества могут быть все входящие в него подмножества – от нуля элементов (пустое множество) до всех возможных значений базового типа. Кстати, в Тurbo Pascal допускается использование (например, в операторах присваива­ния) явно заданных значений множественного типа, подобно, например, целочисленным или вещественным значениям. В этом случае элементы множества задаются через запятую и все значение заключается в квадратные скобки. Например:

х:=[1,3];

х:=[];

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

В качестве базового для множественного типа А2 задан диапазон а..е. Переменная Y, принадлежащая множественному типу А2, может принимать значения, соответствующие всем подмножествам, входя­щим в это множество (всегозначения).

Наконец, в качестве базового для множественного типа А3 выбран стандартный тип Char. Число значений, которые может принимать переменная Z (объявленная как принадлежащая типу А3), равно 2256, причем значения эти представляют собой произвольные наборы символов из таблицы ASCII. Например, переменная Z может иметь значение

[‘3’, ‘f’, ‘(‘, ‘#’, ‘п’, ‘Л’]

Значение переменной Z можно представить и так:

[сhr(45),сhr(54),сhr(58),сhr(65),сhr(73),сhr(78),сhr(89)].

Помимо того, что множество может включать произвольное число элементов, имеет место еще одно отличие множеств от массивов. Если массив – это упорядоченная совокупность элементов, то в множестве порядок элементов никак не фиксируется. Так. [1,2,3,4,5] и [5,2,1,4,3] – это одно множество. Кроме того, все элементы в множестве должны быть различными. Иными словами, [1,2,3] и [1,1,2,3,3,3] – это также одно множество.

Представление множества возможно путем перечисления входящих в него элементов или заданием диапазона (если члены множества образуют неразрывную последовательность), т. е. множество [1,2,3,4,5] можно также представить как [1..5]. Допускается сочетание двух методов: [1..5,7,9].

Число элементов множества в Turbo Pascal не должно превышать 256 (причем, для целочисленных типов эти значения должны лежать в диапазоне (0,...,255). Вследствие этого ограничения в качестве базовых типов для множеств (из стандартных типов) могут служить только Byte, Char и Boolean. Не удастся использовать для множества в качестве базового, например, тип Integer, хотя подходят интервальные типы, образованные на основе integer.

2.4.3.1. Применимые действия. Набор допустимых для множеств операций включает проверку принадлежности элемента множеству; объединение, пересечение и вычитание множеств; сравнение множеств (проверку равенства и неравенств множеств, а также проверку принадлежности одного множества другому).

Проверка принадлежности элемента множеству

Для этой операции в Turbo Pascal имеется специальный оператор IN. Выражение с этим оператором возвращает значение типа Boolean. Вот пример использования оператора IN:

а in [1,3,5,7,9]

Это выражение проверяет, принадлежит ли значение переменной A данному множеству и возвращает значение TRUE либо FALSE. В случае, если бы оператора IN не существовало, нам пришлось бы воспользоваться гораздо более громоздким выражением для проверки данного условия:

(а=1) оr (а=3) оr (а=5) оr (а=7) оr (а=9)

В случае, если переменная А принадлежит множеству [1,3,5,7,9] оба выражения возвратят значение TRUE. Еще примеры:

3 in [1,3,5,7,9];

4 in [1,3,5,7,9];

Эти выражения возвратят значения TRUE и FALSE соответственно.

Объединение, пересечение и вычитание множеств

Эти операции, будучи применены к двум множествам, формируют третье. В Turbo Pascal эти операции обозначаются символами: + (объединение), * (пересечение), - (вычитание).

В результате объединения двух множеств А и В формируется третье, содержащее все элементы, встречающиеся в первых двух множествах (см. рис.3). Примеры можно видеть в табл.8.

Таблица 8

Примеры объединения двух множеств

Объединение множеств

Результат

[1,2,3,4,5]+[3,4,5,6,7]

[1,2,3,4,5,6,7]

[1,2]+[3,4]

[1,2,3,4]

[‘a’,’b’,’c]+[‘A’,’B’,’C]

[‘a’,’b’,’c’,’A’,’B’,’C]

[‘1’,’3’,’5’,’7’,’9’]+[‘1’,’3’,’5’,’A’,’B’]

[‘1’,’3’,’5’,’7’,’9’,’A’,’B’]

Часто возникает необходимость добавить в множество новый элемент (частный случай операции объединения). Эта задача может быть решена следующим образом:

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

В результате пересечения двух множеств А и В формируется третье множество, содержащее только элементы, одновременно принадлежащие первым двум множествам (см. рис.3). Примеры можно видеть в Табл.9.

Таблица 9

Примеры пересечения двух множеств

Пересечение множеств

Результат

[1,2,3,4,5]*[3,4,5,6,7]

[3,4,5]

[1,2]*[3,4]

[]

[‘a’,’b’,’c]*[‘A’,’B’,’C]

[]

[‘1’,’3’,’5’,’7’,’9’]*[‘1’,’3’,’5’,’A’,’B’]

[‘1’,’3’,’5’]

При вычитании множества В из множества А формируется третье множество, содержащее только элементы, принадлежащие множеству А и не принадлежащие множеству В (см. рис.3). Примеры можно видеть Табл.10.

Таблица 10

Примеры вычитания двух множеств

Вычитание множеств

Результат

[1,2,3,4,5]-[3,4,5,6,7]

[1,2]

[1,2]-[3,4]

[1,2]

[‘a’,’b’,’c]-[‘A’,’B’,’C]

[‘a’,’b’,’c]

[‘1’,’3’,’5’,’7’,’9’]-[‘1’,’3’,’5’,’A’,’B’]

[’7’,’9’]

Необходимо иметь в виду, если в случае объединения и пересечения множества А и В поменять местами, результат не изменится, но, однако это вовсе не так для вычитания множеств. Пример можно видеть в табл.11.

Таблица 11

Перестановка множеств при вычитании

Вычитание множеств

Результат

[‘1’,’3’,’5’,’7’,’9’]-[‘1’,’3’,’5’,’A’,’B’]

[’7’,’9’]

[‘1’,’3’,’5’,’A’,’B’]-[‘1’,’3’,’5’,’7’,’9’]

[‘A’,’B’]

Операции объединения, пересечения и вычитания множеств А и B можно представить графически, если изобразить эти множества в виде некоторых фигур (например, кругов), закрашенные части которых соответствуют множествам-результатам (рис.3).

Рис. 3. Объединение, пересечение и вычитание множеств

Сравнение множеств

К операциям сравнения множеств относятся проверка равенства неравенства множеств, а также проверка принадлежности одного множества другому. Символы, которыми в Turbo Pascal обозначаются эти операции, представлены в табл.12.

Таблица 12

Операции сравнения множеств

Обозначение

Действие

=

Проверка равенства множеств

<> 

Проверка неравенства множеств

<=

Проверка вхождения множества слева в множество справа

>=

Проверка вхождения множества справа в множество слева

Результат сравнения представляет собой значение типа Boolean (TRUE или FALSE – в зависимости от успеха проверки). Два сравниваемых множества должны иметь один базовый тип.

Операции = и <> проверяют, совпадает ли набор элементов в сравниваемых множествах. Примеры этих операций можно видеть в табл.13 и 14.

Таблица 13

Проверка равенства множеств

Сравниваемые множества

Результат

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

FALSE

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

TRUE

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

TRUE

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

FALSE

Таблица 14

Проверка неравенства множеств

Сравниваемые множества

Результат

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

TRUE

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

FALSE

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

FALSE

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

TRUE

Операции <= и >= проверяют, входит ли одно множество в другое. Множество слева входит в множество справа, если все элементы левого множества встречаются среди элементов правого множества. Примеры проверок по вхождению одного множества в другое представлены втабл.15 и 16.

Таблица 15

Проверка вхождения левого множества в правое

Сравниваемые множества

Результат

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

FALSE

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

TRUE

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

TRUE

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

FALSE

Множество справа входит в множество слева, если все элементы правого множества встречаются среди элементов левого множества.

Таблица 16

Проверка вхождения правого множества в левое

Сравниваемые множества

Результат

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

TRUE

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

FALSE

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

FALSE

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

TRUE

2.5. Совместимость типов

Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 4