Мы отметили, что обращение к элементам записи происходит с помощью уточнённого имени. Оператор присоединения позволяет упростить обращение к элементу записи. Имя записи выносится в заголовок оператора присоединения, а в блоке Begin – end используются только имена элементов записи.
Оператор присоединения имеет вид:
With имя_записи do
Begin
Операторы
End;
Пример. Для 1-ой экзаменационной ведомости (списка 1) оператор присоединения можно записать так:
With C1 do
Begin
Read(N);
Summa := Ball[1] + Ball[3];
End;
Пример. Имеется ведомость учащихся с оценками:
Иванов Иван 2
Петров Пётр 2
Сидоров Сидор 3
Составить программу для вычисления среднего балла.
Поскольку в каждой строке ведомости представлены данные различного типа, введём запись с именем СПИСОК, состоящую из двух полей:
Name – фамилия и имя – упакованный массив из 15 символов;
Ball – оценка – целое число.
Для вычисление среднего балла Midball находится сумма всех оценок Summa, которая делится на число студентов N.
Program W123;
Const N = 3; (* число учащихся в списке *)
M = 15; (* максимальная длина Name *)
Type T = Record
Name: Packed Array [1..M] of Char;
Ball: Integer;
End;
Var Spisok: T;
I, K: Integer; (* параметры цикла *)
Midball: Real; (* средний балл *)
Summa: Integer; (* сумма оценок *)
Begin
Summa := 0;
Writeln(‘ введите таблицу ‘);
For I := 1 to N do
Begin
For K := 1 to M do
Read(Spisok.Name[K]);
Read(Spisok.Ball);
Summa := Summa + Spisok.Ball;
End;
Midball := Summa / N;
Writeln(‘----------------------------‘);
Writeln(‘ средний балл = ‘, Midball: 5: 2);
End.
Описание записи сделано в разделе Type, где Т – имя типа. В разделе переменных Var указано, что переменная СПИСОК тип Т.
Раздел операторов состоит из двух циклов: один вложен в другой. Внешний цикл с параметром I выполняется столько раз, сколько имеется фамилий в ведомости (в данном случае N = 3). Внутренний цикл с параметром К предназначен для ввода фамилии и имени. На фамилию и имя отводится поле из 15 позиций. Лишние позиции поля заполняются пробелами. Внутри поля фамилию и имя можно располагать свободно, например:
_ _ _ _ Иванов _ Иван
или _ _Иванов _ Иван_ _
или _ _ _Иванов _ Иван_
или _ Иванов_ _ Иван_ _
После имени следует оценка.
Пример. Присвоить звание “отличник” тем, у кого по всем предметам пятёрки.
Из исходного списка С1, в котором содержатся фамилии и оценки, нужно сформировать другой список С2, состоящий из отличников. Для формирования списков используется массив массивов.
Найти подобные члены для переменной А и вычислить суммарный коэффициент. Один элемент многочлена можно считать записью, так как он состоит из данных различного типа – коэффициента (число) и буквы.
Введём обозначения:
М1 – элемент многочлена (запись),
М2 – результирующий элемент (запись),
Coef – коэффициент (элемент записи),
Buk – буква (элемент записи),
Elem – тип записи,
Sum – сумму коэффициентов.
Program Ex4;
Type Elem = Record (* тип элемента *)
Coef: Integer; (* коэффициент *)
Buk: Char; (* буква *)
End;
Var M1: Elem; (* входной элемент *)
M2: Elem; (* выходной элемент *)
Sum: Integer; (* сумма коэффициентов *)
Begin
Sum := 0;
Writeln(‘ введите многочлен ‘);
While Not EOLN do (* end of line *)
Begin
Read(M1.Coef, M1.Buk);
If M1.Buk = ‘A’ then Sum := Sum + M1.Coef;
End;
M2.Coef := Sum;
M2.Buk := ‘A’;
Writeln(‘подобный член = ‘, M2.Coef: 3, M2.Buk);
End.
Запись - это комбинированный тип, сложная переменная с несколькими компонентами. В отличие от массивов компоненты записи (поля) могут иметь разные типы, и доступ к ним осуществляется не по индексу, а по имени поля.
Записи могут входить в качестве компонентов в другие переменные, например, можно сформировать массив записей.
К каждому компоненту записи можно обратиться, используя имя переменной типа записи и имя поля, разделённых точкой.
В области действия оператора присоединения With имена переменных-записей и полей, указанные в его заголовке, можно опускать. Транслятор автоматически формирует полные имена. В области действия оператора присоединения нельзя изменять элементы списка переменных-записей и полей, указанные в заголовке.
Пример. Определить число студентов 1974 г. рождения.
Type Student = Record
Name: Array [1..15] of Char;
Date: Integer;
End; { of record }
Var Grope: Array [1..30] of Student;
K, I: Integer;
Begin
K := 0;
For I := 1 to 30 do
With Grope[I].Date do
If Date = 1974 then K := K + 1;
Writeln(K);
End.
В данном примере в заголовке оператора With стоит Grope[I] – элемент массива, зависящий от параметра I, поэтому оператор присоединения вставлен внутрь цикла по I.
Записи с вариантами
При определении комбинированного типа в него можно включать вариантную часть. Это означает, что разные переменные, хотя они и относятся к одному типу, могут иметь различные структуры. Например, пусть необходимо задать информацию о некотором человеке, указав фамилию и год рождения, а также, если это мужчина, то сообщить, военнообязанный ли он и какую имеет специальность; если это женщина, то указать, замужем ли она и сколько имеет детей:
Type Pol = (Mug, Gen);
Chel = Record
Fam: Array [1..10] of Char;
God: 1900..2000;
MG: Pol; { заголовок вариантной части }
Case Pol of
Mug: (Voen: Boolean; Spec: Array [1..15] of Char);
Gen: (Zamugem: Boolean; Dety: Integer);
End; (* of record *)
Var Ch1, Ch2: Chel;
Вариантная часть записи начинается оператором Case и следует за общей частью; после её окончания в записи не появляться никакие другие поля, поэтому оператор Case не закрывается служебным словом End.
Обычно некоторое поле общей части указывает вариант. В примере это поле MG, называемое полем признака или дискриминации.
Все варианты описываются внутри оператора Case. Каждый вариант характеризуется задаваемым в скобках списком описаний присущих ему компонентов.
Перед списком стоит одна или несколько меток. Тип этих меток указывается в заголовке вариантной части (в отличие от оператора варианта, где селектором варианта является выражение, а не тип). Тип должен быть скалярным (не массивы и не записи), При этом он задаётся именем.
В явном виде указывать тип в заголовке не разрешается.
Часто для сокращения записи поле признака (дискриминант) включается в заголовок вариантной части:
Case MG: Pol of
Для переменной Ch1 типа Chel можно написать следующие операторы присваивания:
Ch1.Fam := ‘Solomatin’;
Ch1.God := 1977;
Ch1.MG := Mug;
Ch1.Voen := True;
Ch1.Spec := ‘Programmist’;
Задав значение поля признака MG (некоторую константу типа Pol), можно присваивать новые значения только полям вариантной части, помеченных такой же константой.
Хотя никакого контроля поля селектора при обращении к компоненту из вариантной части не производится, для надёжности работы программы следует придерживаться этого правила.
В любой записи может быть только одна вариантная часть, и, если она есть, она должна располагаться за всеми фиксированными полями.
Пример.
Type Alfa = Array [1..10] of Char;
Variety = (Book, Journal, Newspaper);
Name = Record
First, Last: Alfa;
End; (* of Name *)
Edition = Record
Name1: Name;
Title, Publishers: Alfa;
Case V: Variety of
Book: (Years: Integer);
Journal: (Number: 1..12;
Volume: Integer;
YearJ: 1900..2000);
Newspaper: (Day: 1..31;
Month:1..12;
YearN: Integer);
End; (* of Edition *)
………………………
Var E: Edition;
…………………….…
E.Name1.First := ‘Niklau’;
E.Name1.Last := ‘Wirth’;
E.Title := ‘Pascal’;
E.Publichers := ‘Springer’;
E.V := Journal;
E.Number := 5;
E.Volume := 12;
E.YearJ := 1972;
В описании записи разрешается использовать только одну вариантную часть, причём она должна быть записана после фиксированной части. Однако в вариантной части, в свою очередь, может появиться вариантная часть, следовательно, могут быть вложенные друг в друга вариантные части.
При записи варианта обязательно присутствие круглых скобок, даже если в них ничего не заключается. В этом случае записывается просто: ( ).
Пример. Определить площадь геометрической фигуры.
X и Y – координаты одного из углов прямоугольника или треугольника или центра окружности.
Area – площадь.
Skew – угол наклона одной из сторон прямоугольника.
Side1 и Side2 – длины двух смежных сторон прямоугольника.
Inclin – угол наклона одной из сторон треугольника.
Side – её длина.
Angle1 и Angle1 – углы, образованные с нею двумя другими сторонами.
Diameter – диаметр окружности.
Program Opr;
Const Pi = 3.141592;
Type Figure = (Triangle, Rectangle, Circle);
GeometricFigure = Record
X, Y: Real;
Area: Real;
Case Shape: Figure of
Triangle: (Inclin, Side, Angle1,Angle2: Real);
Rectangle: (Skew, Side1, Side2: Real);
Circle: (Diameter: Real);
End; (* of record *)
Var GFig: GeometricFigure;
Begin
……………
Case GFig.Shape of Triangle: GFig.Area := 0.5*SQR(GFig.Side)/(cos(GFig.Angle1)/