Каждый комбинированный тип - это множество записей одной и той же структуры, т.е. имеющих одно и то же число полей, названия и типы которых одинаковы. Например, все записи комбинированного типа «дата» имеют такую структуру: число: целое от 1 до 31 месяц: название месяца год: любое целое число В Паскале этот тип описывается следующим образом: type дата = record число: 1..31; месяц: (янв,лев,...,дек); год: integer end; Комбинированные типы type студент = record ФИО: record фамилия, имя, отчество: string end; пол: (муж,жен); группа: ; оценки: array[1..3] of 2..5 end;
Комбинированные типы В общем случае комбинированный тип описывается так: type = ; комбинированный тип варианта record end ; секция полей ; имя поля, : тип
Операции над записями Единственная стандартная операция, применимая к записям как единым объектам, - это присваивание: v1:=v2 где v1 и v2 - переменные-записи одного и того же комбинированного типа. ::=. Пример Пусть имеется переменная-запись d типа дата. Как уже говорилось, записи этого типа содержательно могут быть ошибочны, т.к. допускаются и незаконные даты вроде «31 июнья». Поэтому давайте определим логическую функцию верная дата(d), которая выдает true, если d - законная дата, и значение false иначе. function верная дата(var d:дата):boolean; var посл:28..31; begin {определение последнего числа месяца} case d.месяц of янв,мар,май,июль,авг,окт,дек: посл:=31; апр,июнь,сен,ноя: посл:=30; лев: if(d.год mod 400=0) or (d.год mod 4=0) and (d.год mod 100<>0) then посл:=29 else посл:=28 end; верная дата:=(d.год<>0) and (d.число<=посл) end;
Оператор присоединения В простейшем случае он записывается так: with R do S где with (с) и do - служебные слова, R - переменная-запись, а S - любой оператор Как обращаться к этой функции? Например, можно так: сегодня.число:=29; сегодня.месяц:=лев; сегодня.год:=1900; if верная дата(сегодня) then... Например, приведенные выше операторы для вызова функции верная дата можно записать так: with сегодня do begin число:=29; месяц:=лев; год:=1900 end; if верная дата(сегодня) then.... Приставку сегодня к именам полей число, месяц и год оператор присоединения добавит сам. В этом и выгода от данного оператора - он избавляет нас от необходимости перед каждым полем записи сегодня писать имя этой записи и точку. Но - и на это надо обратить внимание - такое можно делать только в операторе, сразу следующим за do, на остальные операторы данное правило не распространяется.
В общем виде обращение к оператору присоединения выглядит так: with R1, R2,..., Rn do S что полностью эквивалентно: with R1 do with R2 do... with Rn do S оператор присоединения with do переменная- запись, оператор
Пример Рассмотрим пример на использование оператора присоединения. Вспомним ранее определенный тип студент и определим еще один тип данных: type группа=array[1..30] of студент; объектами которого являются 30-элементные массивы, содержащие информацию о группах студентов. Давайте опишем процедуру Отличники(Гр), которая выводит фамилии и имена всех студентов-отличников из группы ГР. Идея решения проста: в цикле рассматриваем каждого студента из группы, подсчитываем число пятерок у него и, если их четыре (по числу экзаменов), выводим на экран подполя фам и имя из поля ФИО. На Паскале это записывается так:
procedure Отличники(ГР: группа); var i,j,k: integer; begin for i:=1 to 30 do {цикл по студентам} with ГР[i], ФИО do begin {подсчет пятерок у i-го студента} k:=0; for j:=1 to 4 do if оценки[j]=5 then k:=k+1; {отличник -> вывод} if k=4 then writeln(фам, _, имя) end end; Отметим, что использование оператора with избавило нас от выписывания длинных текстов if ГР[i].оценки[j]=5 then... и writeln(ГР[i].ФИО.фам, _, ГР[i].ФИО.имя) Порядок перечисления переменных-записей в заголовке оператора присоединения должен быть именно таким, как указано, т.к. этот оператор эквивалентен with ГР[i] do with ФИО do... поэтому имя ФИО попадает в область действия записи ГР[i] и может указываться без приставки «ГР[i].».