
3.4 Оператор присоединения
Используя "точечную" нотацию при обращении к полям записи, мы выписывали всю цепочку имен, начиная с высшего уровня до имени конкретного объекта (или поля), к которому шло обращение. Оператор присоединения позволяет упростить обращение к полю записи. Имя записи выносится в заголовок оператора присоединения, а в теле оператора используются только имена полей записи.
Формат оператора присоединения:
with <имя записи-переменной> do
<оператор>;
Если после do стоят несколько операторов (составной оператор), то их заключают в операторные скобки, и оператор присоединения имеет формат:
with <имя записи-переменной> do
begin
<оператор 1>;
<оператор 2>;
. . . . .
<оператор n>;
end;
Имя записи-перменной, указанное в заголовке оператора присоединения, автоматически присоединяется ко всем именам полей, упомянутым в теле оператора with.
Пример записи оператора присоединения:
а) для структуры 1-го типа:
. . . . . .
with STUDENT do
begin
Read(FIO); {вводим фамилию студента: Иванов И.И.},
Read(STIP); {вводим стипендию студента 125},
K := 5;
N_ZACH := 987671;
GR := 56;
Write(FIO, '':3, K, '':3, GR)
end;
. . . .
б) для структуры 2-го типа (вложенные записи):
. . . .
with STUDENT do
begin
Read(GRUP.FIO); {вводим фамилию студента: Федорова А.А.},
Read(GRUP.STIP); {вводим стипендию студента: 83},
K:= 5;
GRUP.N_ZACH := 987650;
GRUP.GR := 53;
Write(GRUP.FIO, '':3, K, '':3, GRUP.GR)
end;
. . . .
В одном заголовке оператора with можно задать не одно имя записи, а целый список имен различных записей (от высшего уровня к низшему), разделенных запятой.
. . . .
with STUDENT,GRUP do
begin
Read(FIO); {вводим фамилию студента: Петрова Н.Н.},
Read(STIP); {вводим стипендию студента: 105},
K := 5;
N_ZACH := 987654;
GR := 55;
Write(FIO, '':3, K, '':3, GR)
end;
. . . .
Приведенная форма записи оператора with эквивалентна следующей:
. . . .
with STUDENT do
with GRUP do
begin
Read(FIO); {вводим фамилию студента: Петрова Н.Н.},
Read(STIP); {вводим стипендию студента: 105},
K:=5;
N_ZACH := 987654;
GR := 55;
Write(FIO, '':3, K, '':3, GR)
end;
. . . .
Если использовать оператор with в форме: . . . .
with STUDENT.GRUP do
begin
Read(FIO); {вводим фамилию студента: Петрова Н.Н.},
Read(STIP); {вводим стипендию студента: 105},
K:= 5;
N_ZACH := 987654;
GR := 55;
Write(FIO, '':3, K, '':3, GR)
end;
. . . .
то программа работать не будет, так как при таком использовании оператора with выполняется работа только с полями записи GRUP (см. также описание «точечной» нотации. Поэтому оператор K:= 5; следует исключить ( K – поле записи STUDENT, но не GRUP) и в операторе Write удалить фрагмент (K, ‘’:3,).
Пример 1. Дана сводная ведомость результатов экзаменов группы в сессию:
Иванов Н.П. 5 4 3 4
Петров А.П. 5 4 5 3
Сидорова Е.Е. 3 3 4 3
. . . .
Найти средний балл группы и напечатать список студентов, имеющих средний балл выше среднего по группе.
План решения.
1. Пусть в группе n студентов. Опишем массив ST, состоящий из записей, содержащих данные по каждому студенту.
2. Введем этот массив, одновременно вычисляя средний балл каждого студента и накапливая сумму S - сумму средних баллов.
3. Находим средний балл по группе: S=S/n.
4. Печатаем список студентов, которые учатся хорошо, т.е. имеют средний балл выше среднего по группе.
program ZAPISI_1;
uses crt;
const n=25;
type
STUDENT=record
fio:string[20];
bal:array[1..4] of 2..5;
sr_bal:real
end;
var
ST:array[1..n] of STUDENT;
i,j:integer; S:real;
begin clrscr; S:=0;
for i:=1 to n do
with ST[i] do
begin Write('Введите фамилию студента: ');
Readln(fio); sr_bal:=0;
Writeln('Введите оценки:');
for j:=1 to 4 do
begin read(bal[j]);
sr_bal:=sr_bal+bal[j]
end;
Readln;
sr_bal:=sr_bal/4;
S:=S+sr_bal
end;
S:=S/n;
Writeln('Средний балл группы равен ',S:4:2);
Writeln;
Writeln('Список студентов, которые учатся хорошо:');
for i:=1 to n do
if ST[i].sr_bal>S then Writeln(ST[i].fio,'':4,ST[i].sr_bal:4:2)
end.
Для тестирования зададим в разделе const n=3.
Исполнение программы:
Введите фамилию студента:
Иванов Н.П.
Введите оценки:
5 4 3 4
Введите фамилию студента:
Петров А.П.
Введите оценки:
5 4 5 3
Введите фамилию студента:
Сидорова Е.Е.
Введите оценки:
3 3 4 3
Средний балл группы равен 3.83
Список студентов, которые учатся хорошо
Иванов Н.П. 4
Петров А.П. 4.25
Пример 2. В справочной аэропорта хранится расписание полетов на следующие сутки. Для каждого рейса указаны его номер, тип самолета, пункт назначения, время вылета, время в полете. Определить номера рейсов, время вылета и типы самолетов, прибывающих в заданный пункт назначения до 12 часов.
program ZAPISI_2;
uses crt;
const n=30; { n - общее число рейсов в расписании}
type
time_rec= record
chas:0..24;
min:0..60
end;
data_rec=record
day:1..31;
mec:1..13
end;
info_samolet=record
punkt_naznach:string[15];
nomer_reisa:integer;
tip_samoleta:string[10];
data_vileta:data_rec;
time_vileta:time_rec;
time_poleta:time_rec;
end;
var
raspisanie:array [1..n] of info_samolet;
gorod:string[15];
i,k:integer;
time:time_rec;
begin clrscr;
Writeln('':10,'РАСПИСАНИЕ РЕЙСОВ');
for i:=1 to n do
with raspisanie[i] do
begin
Writeln('Введите ');
Write('пункт назначения:','':14);
Readln(punkt_naznach);
Write('номер рейса:','':19); Readln(nomer_reisa);
Write('тип самолета:','':18); Readln(tip_samoleta);
Write('дата вылета /день месяц/:','':6);
Readln(data_vileta.day, data_vileta.mec);
Write('время вылета /час мин/:','':8);
with time_vileta do Readln(chas,min);
Write('время полета /час мин/:','':8);
with time_poleta do Readln(chas,min);
end;
Writeln;
Write('Введите пункт прибытия:','':8); Readln(gorod);
for i:=1 to n do
with raspisanie[i] do
begin
k:=time_vileta.chas+time_poleta.chas;
if (time_vileta.min+time_poleta.min) >=60 then k:=k+1;
if (k mod 24 <12) and (punkt_naznach=gorod) then
begin
Writeln('':11, 'номер рейса:', '':8, nomer_reisa);
Writeln('':10,'тип самолета:','':8,tip_samoleta);
with time_vileta do
Writeln('':10,'время вылета:' , '':8, chas, 'час ':3, min, 'мин');
end
end
end.
Для тестирования зададим в разделе const n=3.
Исполнение программы:
РАСПИСАНИЕ РЕЙСОВ
Введите
пункт назначения: Москва
номер рейса: 123
тип самолета: ТУ-124
дата вылета /день месяц/: 03 02
время вылета /час мин/: 02 10
время полета /час мин/: 09 59
Введите
пункт назначения: Санкт-Петербург
номер рейса: 345
тип самолета: ИЛ-16
дата вылета /день месяц/: 03 02
время вылета /час мин/: 08 45
время полета /час мин/: 02 30
Введите
пункт назначения: Москва
номер рейса: 127
тип самолета: АН-24
дата вылета /день месяц/: 03 02
время вылета /час мин/: 05 45
время полета /час мин/: 04 50
Введите пункт прибытия: Москва
номер рейса: 127
тип самолета: АН-24
время вылета: 05 45
Замечание. Если данные time_vileta и time_poleta опишем как поля записи data_rec, то в программе изменится:
- описание записей data_rec и info_samolet;
- запись оператора присоединения и обращение к полям day, mec.
program ZAPISI_2_1;
uses crt;
const n=30; { n - общее число рейсов в расписании}
type
time_rec= record
chas:0..24;
min:0..60
end;
data_rec=record
day:1..31;
mec:1..13;
time_vileta:time_rec;
time_poleta:time_rec;
end;
info_samolet=record
punkt_naznach:string[15];
nomer_reisa:integer;
tip_samoleta:string[10];
data_vileta:data_rec;
end;
var
. . .
begin clrscr;
Writeln('РАСПИСАНИЕ РЕЙСОВ');
for i:=1 to n do
with raspisanie[i], data_vileta do
begin
. . .
Write('дата вылета /день месяц/:','':6);
Readln(day, mec);
. . .
end;
. . . . . .
for i:=1 to n do
with raspisanie[i], data_vileta do
begin k:=time_vileta.chas+time_poleta.chas;
if (time_vileta.min+time_poleta.min) >=60 then k:=k+1;
. . .
end
end.
Возможны и другие варианты оформления программы.