В.Г. Абрамов, Н.П. Трифонов, Г.Н. Трифонова - Введение в язык Паскаль (1107618), страница 47
Текст из файла (страница 47)
имя поля.Аналогичным образом, если значения комбинированного типа с именемКнига, введенного выше, объединены в массив с помощью описания переменной БиблиотекаvarБиблиотека: array С 1..100003 of Книга;то при поступлении в библиотеку нового издания книги, запись о предыдущем издании которой в массиве Библиотека имеет номер 117, эту записьможно скорректировать (при изъятии из библиотеки предыдущего издания) с помощью следующего оператора присваивания:БиблиотекаС1173.годиздания:=1986;19610.2.
Иерархические записиДо сих пор мы рассматривали такие записи, у которых значения отдельныхее полей были скалярными величинами или строками. Но поскольку на типзначений полей в паскале не накладывается ограничений, то отдельнымикомпонентами записи могут быть также нетривиальные структуры данных,например тоже записи.Обратим внимание на следующее обстоятельство. Как правило, записьпредставляет собой модель какого-либо реального объекта: человека, машины, книги и т.д., а отдельные поля записи представляют те или иные характеристики этого объекта. Однако количество характеристик может бытьдовольно значительным, а в каждом конкретном случае, т.е.
при решенииконкретной задачи, нас, как правило, интересуют не все, а только частьиз них. Например, при создании узкоспециализированной информационнойсистемы "Успеваемость студентов" на каком-либо факультете в записи,относящейся к отдельному студенту, достаточно — помимо фамилии, имении отчества студента — иметь информацию о том, какие оценки им былиполучены на экзаменах в каждую сессию по каждому предмету (и, возможно, информацию об имевших место пересдачах).
В подобного рода информационной системе в запись, вообще говоря, нет необходимости включатьинформацию о дате рождения студента, его семейном положении, наличииспортивных разрядов и т.п. Наоборот, в системе типа "Кадры" вряд литребуется держать информацию об оценках на экзаменах в вузе научныхсотрудников — там нужна информация другого рода, например та, которуюмы обычно указываем в личном листке по учету кадров; в информационной системе типа "Здоровье" каждая запись должна содержать свою, специфичную для данной системы информацию.Так что при определении комбинированного типа необходимо предварительно — исходя из назначения составляемой программы — принять решение о том, какая информация должна содержаться в записи, и исходя изэтого решать вопрос о том, сколько полей должна содержать запись данного типа, и какой тип значения должен содержаться в том или ином полеВ связи с этим при рассмотрении примеров, не связанных с решениемкакой-либо конкретной задачи, не следует задаваться вопросом о том,почему взята именно такая структура записи, а не иная, поскольку приводимые примеры иллюстрируют лишь возможности создания сложныхструктур данных с помощью комбинированного типа.Тип значения поля записи может быть определен двумя способами:непосредственно задан в описании комбинированного типа, либо указаноимя ранее описанного типа.
В последующих примерах мы будем активнопользоваться и тем, и другим способом.Приведем пример комбинированного типа с именем Сотрудник, который будет определять довольно сложную иерархическую структуру данных. Но прежде чем будет выписано описание собственно типа Сотрудник,дадим описание нескольких вспомогательных типов:typealfa=packed array CI..
15] o-f char;Дата=гесогЬ197день: 1. . 31;нес: (яьв , Фев , март, апр ,май, июнь ,июль,авг,сент,окт,нояб,дек);год: integerend;CoTpyAHHK=recordФио: record Фам,имя,отч: al-fa end;рожд: Дата;пол:обр:зарплата:(муж,жен);(нач,сред,сртехн,высшее);integer;учстеп:Сбезст,кандидат,доктор);учзван:(беззв,доцент,снс,профессор);домадр: recordиндекс:iteger;город,улица: al-fa;дом,корп,кв:integerend;тел; record дом,служ: integer end;члпрофс: booleanend;К а к в и д н о , значение типа С о т р у д н и к будет иметь и е р а р х и ч е с к у ю с т р у к т у р у . П р и этом н а н и ж н е м у р о в н е иерархии ф и г у р и р у ю т л и ш ь п р о с т ы етипы данных и строки.Теперь м о ж н о в в е с т и в у п о т р е б л е н и е п е р е м е н н у ю , н а п р и м е р Чел, типаСотрудник:varЧел: Сотрудник;Значение этой п е р е м е н н о й м о ж н о создать, о п р е д е л и в значения всех полей, например, следующим образом:Чел.
ФИО. имя: = ' АЛЕКСАНДР';Чел. Фио. Фам: * ' СЕРГЕЕВИЧ';Чел . Фио. отч: = 'ИВАНОВ';Чел.рожд.день:=13;Чел.рожд.мес:=март;Чел.рожд.год:=1952;Чел.пол:=муж;Чел.обр:=высшее;Чел.зарплата:=200;Чел.учстеп:=кандидат;Чел.учзван:=доцент;Чел.домадр.индекс:=117232;Чел . домадр. город: = ' МОСКВА';Чел.домадр.улица: = 'ЛЕНИНСКИЙ_ПРОСП' ;Чел.домадр.дом: =117;Чел.домадр.корп: =3;Чел.домадр.кв:=235;Чел.тел.дом:=1335544;Чел.тел.служ:=1395398;Чел.члпрофс:=false;В дальнейшем, в случае необходимости, значения отдельных полейзаписи можно изменить, например:Чел.учстеп:=доктор;Чел.члпрофс:=true;Как видно из приведенного выше примера, создание значения переменной комбинированного типа представляет собой довольно громоздкуюпоследовательность операторов присваивания, поэтому в дальнейшихпримерах мы не будем выписывать соответствующие операторы,а предположим, что значения соответствующих переменных определяютсянекоторой процедурой, либо сами примеры будут представлять описанияпроцедур или функций, в которых задаются формальные параметры комбинированных типов.Пример10.2.
Дать описание процедуры, определяющей статистикуоценок, полученных студентами курса (сколько двоек, троек, четверок ипятерок было получено студентами курса в сессию). Считать, что в разделеконстант и типов заданы следующие описания:constчислогр=16;числост=25;числоэкэ=5;typeстрока:'packed array С1..153of char;Фио: recordфам,имя,отч:строкаend;оцзкз=аггау С 1..числоэкзЭ of 2..5;CTyAeHT=recordимястуд:пол:возраст:сессия:стипендия:Фио;(муж, жен);integer;оцэкз;booleanend;группа=аггауС1..числостЗ of студент;199Kypc=recordсостав: array С1..числогрЗ of группа;стат: record дв,тр,чт,пт:integer endendС использованием введенных выше типов и констант описание процедуры, которая подсчитывает статистику полученных студентами оценок(число пятерок, четверок, троек и двоек), может выглядеть, например,следующим образом:procedure статистика<var курс1:var i,j,k:Курс);integer;begin•for i: = l to числагр dofor j:=lto числост dofor k: = l to числоэкз docase курс 1 .
состав Г i , j 3 . сессия Г. k 3 of2: к-ypcl. стат.дв : =курс1. стат. дв + 1;3: к у р с1.стат.тр:=курс1.отат.тр+1;4:Kypcl.стат.чт:=курс1.стат.чт+1;5: курс1 . стат.пт:=курс1.стат.пт+1endend;Заметим, что формальный параметр курс1 задан как парамегр-переменная. Это существенный факт, потому что результаты подсчета числа оценокзаносятся в поля стаг.дв, стат.тр, стат.чт, стат.пт соответствующей переменной, которая будет использована как фактический параметр.
Естественно,эта переменная должна иметь тип Курс.10.3. Оператор присоединенияИз приведенного выше примера видно, что при работе с записями получаются слишком длинные тексты программ, гак как все время ириходигсявыписывать полные имена записей (в последнем примере девять разпришлось написать идентификатор курс1). Учитывая, что при работес записями такое выписывание происходит очень часто, в паскале введенспециальный оператор, позволяющий сократить написание частичной переменной комбинированного гипа.
Таким оператором является операторприсоединения, который в простейшем случае имеет вид:with R do Sгде with и do — служебные слова, R — переменная комбинированного типа, S — любой оператор паскаля.Выполнить оператор присоединения - это значит выполнить оператор S.В чем же тогда смысл использования оператора присоединения?Дело в том, что внутри оператора S компоненты комбинированной пере200менной R можно обозначать просто идентификаторами полей.
Например,вместо записи R.p, где р — и м я поля, в операторе S можно писатьпросто р. Используя оператор присоединения, пример 10.2. можно переписать следующим образом (описания типов и констант остаютсяпрежними):procedure статистика(var Kypcl:var i,j,k:Курс)jinteger;beginfor i:=l to числогр do•forto числостdo•for k: = l to числоэкз dowith Kypcl do.case состав С i,j 3•сессия С k] of2: стат.дв:=стат.дв + 1;3sстат.тр:=стат.тр+1;4: с т а т . ч т : - с т а т . ч т + 1 ;5: стат.пт:«стат,пт+1endend;Как видно, текст описания процедуры существенно сократился за счеттого, что внутри оператора присоединения имя курс1 отсутствует.В общем случае оператор присоединения выглядит так:with R l , R2Rn do Sчто полностью эквивалентно:with Rl do with R2, R3, .. ., Rn do SИдентификатор поля в операторе присоединения обозначает компонентукомбинированной переменной из ближайшего объемлющего оператораприсоединения, в котором указана переменная с таким полем.
Следовательно, если две переменные из списка комбинированных переменных оператора присоединения имеют поля, обозначаемые одним и тем же идентификатором, то внутри оператора присоединения этот идентификатор обозначает поле той переменной, которая указана в списке позже.Точное синтаксическое описание оператора присоединения выглядитследующим образом:< оператор присоединения > :: = < заголовок > < оператор >( заголовок > ::= with ( список переменных-записей > do< список переменных-записей > :: = < переменная-запись >{, < переменная-запись )}При определении того или иного комбинированного типа имена отдельных полей могут совпадать с именами переменных.
Путаницы при использовании этих переменных и соответствующих значений полей записи непроисходит в силу того, что в частичной переменной-записи указывается иимя собственно переменной-записи. Однако при использовании оператора.присоединения может возникнуть недоразумение, связанное с тем, чтовнутри него имена переменных-записей опускаются. Возникает вопрос:что обозначает имя внутри оператора присоединения, если и у соответствующей переменной-записи присутствует поле с таким именем, и в разделепеременных введена в употребление переменная с таким же именем?В языке паскаль этот конфликт решается так: предпочтение отдаетсяименам полей записи, т.е.