1. Записи (начало)

Ранее мы рассматривали структурированные данные, состоящие из компонент одного типа (массивы). Однако на практике часто необходимо иметь под одним именем совокупность данных различного типа. Например, информация о студенте может состоять из данных: фамилия, имя, отчество (тип string), домашний адрес (тип string), пол (тип char), номер группы (тип integer), номер комнаты проживания в общежитии (тип integer), изучаемые предметы (тип, массив строк) и т.д.

Для объединения разнотипных данных под одним именем и возможности последующей их обработки в языке Pascal предусмотрен тип данных запись.

Запись - поименованный структурированный тип данных, состоящий из фиксированного количества различных компонент. Определение (описание) данного типа "запись" начинается атрибутом record и заканчивается end.

Между record и end заключается список компонент записи, называемых полями, с указанием их имен и типа каждого поля. Туре имя типа=record идентификатор поля: тип компоненты; идентификатор поля: тип компоненты;

end;

Var идентификатор: имя типа; Возможно и «прямое» описание записи, без предварительного описания типа. Пример описания записи с помощью предварительного задания типа:Туре Car=record Nomer: integer; {номер} Marka: string [20]; {марка автомобиля} FIO: string [40], {ф.и.о. владельца} adres: string [60]; {адрес владельца}end;Var M, V: Car;Либо «прямое» описание:Var М, V: Record Nomer: integer; Marka: string [20];

FIO: string [40]; adres: string [60]; end; Идентификатор поля должен быть уникален только в пределах записи, однако во избежание ошибок лучше его делать уникальным в пределах программы.

Объем памяти, выделяемый в разделе Var, для хранения записи складывается из объемов памяти - суммы длин полей. Значения полей записи могут использоваться в выражениях, при этом в них должны указываться составные (уточненные) имена, так как имена полей в различных записях могут совпадать. Например, чтобы получить доступ к полям записи Саr, необходимо пользоваться именами М. FIO, М. NOMER для записи М, а для записи V - именами V. FIO, V. NOMER. Эти имена можно использовать везде, где применяются обычные имена, например, в операторах присваивания:

М. Nomer:=1678;

V. Nomer:=3789;

М. Marka:'газ-24';

V. Marka:='Таврия';

В операторах ввода-вывода:

writeln (м. marka);

Допускается применение операторов присваивания к записям в целом, если они имеют одинаковые структуры. Так, для приведенного выше описания записей М и V допустимо M:=V;

После выполнения этого оператора значения полей записи V станут равными значениям полей записи М.

В ряде задач удобно пользоваться следующими массивами записей:

Туре Person=record

FIO: string [30];

Prof: string [30); end;

Var List: array [1..50] of Person;

Здесь массив List будет состоять из 50 записей типа Person.

Сама запись может иметь поля любого известного нам типа, в том числе и массивного. Допускается, чтобы поле записи само было записью. Обращение к полям записи с помощью составных имен имеет несколько громоздкий вид, что особенно неудобно при использовании мнемонических идентификаторов длиной более 5 символов. Для облегчения этой ситуации в языке Pascal есть оператор with, который имеет следующий формат:

with имя переменной типа запись do

begin ···················· end.

Один раз указав в операторе with переменную типа запись, затем - в пределах begin... end, стоящих после with, можно работать с именами полей этой записи как с обычными переменными, т.е. без указания перед именем поля имени записи. Например:

без применения оператора with:

М. NOM:=5543;

M.MARKA:='гa3-24';

М. FIO:='Петров П. П.';

М. Adres:='ул. Чкалова, 7, кв.32';

end;

Составить программу учета успеваемости студентов курса, состоящего из шести групп до 30 студентов в каждой группе. Каждый студент сдавал экзамены по пяти дисциплинам: высшая математика, основы информатики, философия, история Украины, архитектура ЭВМ. По каждому предмету можно получить оценки 2, 3, 4, 5. Каждый экзамен можно сдавать до трех раз. Произвести анализ: если у студента имеется три двойки по одному предмету или три непересданные двойки по трем предметам, то он должен быть отчислен; если студент все двойки пересдал, то его нужно поругать.

Program Prim44;

label u,w;

type mo=array[1..5,1..3] of 0..5;

st=record

namb:integer;

fio:string[20];

o:mo; end;

var

gr:array[1..6,1..30] of st;

i,j,k,l,kol_dvoek,v,kgr,n:integer;

md:mo; ch:char;

predmet:string; kst:array[1..6] of byte;

procedure rea_ocenki(fio:string;Var oc:mo);

Label M1,M2,M3,M4;

Var i:integer;

begin

for i:=1 to 5 do

Begin

case i of

1:predmet:='основы информатики';

2:predmet:='высшей математике';

3:predmet:='философии';

4:predmet:='архитектуре ЭВМ';

5:predmet:='истории Украины'; end;

writeln('введите оценку студента  ',fio,' no ',predmet);

M1: readln(oc[i,1]);

if (oc[i,1]<2) or (oc[i,1]>5) then

Begin writeln('введите правильно оценку'); goto M1; end;

if oc[i,1]>2 then Begin oc[i,2]:=0; oc[i,3]:=0; goto M4; end else

M2: writeln('введите вторую оценку студента ',fio,' по ',predmet);

readln(oc[i,2]);

if (oc[i,2]<2) or (oc[i,2]>5) then

Begin writeln('введите правильно оценку'); goto M2; end;

if oc[i,2]>2 then begin oc[i,3]:=0; goto M4; end else

M3: Writeln('введите третью оценку студента ',fio,' по ',predmet);

readln(oc[i,3]);

if (oc[i,3]<2) or (oc[i,3]>5) then

begin writeln('введите правильно оценку'); goto M3; end;

M4: end; end;

BEGIN { начало блока ввода оценок студентов}

writeln('при вводе оценки набираются: 5, если экзамен');

writeln('сдан на 5 и, если были пересдачи, то 2,2,3 ');

z: writeln('до первой положительной оценки');

writeln('задайте количество групп, не более 6 ');

readln(kgr);

for i:=1 to kgr do { установка индекса группы }

begin case i of { определяем группу по i }

1:n:=610;

2:n:=611;

3:n:=612;

4:n:=613;

5:n:=614;

6:n:=615;

else writeln('неправильно задано количество групп'); goto 2; end; end;

writeln('задайте количество студентов в группе ',n);

readln(kst[i]);

for j:=1 to kst[i] do { установка номера студента i в группе }

begin with gr[i,j] do { работать без составных имен }

begin namb:=n; writeln('введите фамилию ',j,' студента гр. ',namb);

readln(fio);

for k:=1 to 5 do { обнуляем массив оценок }

for l:=1 to 3 do

o[k,l]:=0;

writeln('введите оценки студентов ',fio);

rea_ocenki(fio,o); end;end;end;

{ конец ввода оценок студентов }

{ отображение на экране введения оценок }

for i:=1 to kgr do

for j:=1 to kst[i] do

Begin with gr[i,j] do

Begin for k:=1 to 5 do

write(o[k,1],o[k,2],o[k,3],' '); writeln; end; end;

{ конец вывода на экран оценок }

{ начало блока анализа успеваемости студентов }

for i:=1 to kgr do { индекс группы }

for j:=1 to kst[i] do { номер студента }

Begin kol_dvoek:=0; v:=0; { работать без составных имен }

with gr[i,j] do

Begin

for k:=1 to 5 do { номер предмета }

Begin

{ итак, анализируем состояние успеваемости студента, информация }

{ о котором хранится в записи gr[i,j]; так как мы работаем под уп-}

{равлением оператора with gr[i,j], то можно пользоваться не }

{ составными именами полей }

case k of { определить название предмета j }

1:predmet:='основы информатики';

2:predmet:='высшая математика ';

3:predmet:='философия';

4:predmet:='архитектура ЭВМ';

5:predmet:='история Украины'; end;

if o[k,1]=2 then if o[k,2]=2 then if o[k,3]=2 then begin

writeln('студент ',fio,' группы ', namb,' подлежит отчислению так как');

writeln('имеет три двойки по предмету ',predmet);

v:=1; readln; goto w; end { на новый предмет }

else Begin kol_dvoek:=kol_dvoek+2; goto w; end

else Begin kol_dvoek:=kol_dvoek+1; goto w; end;

w: end;

if v=1 then goto u { к новому студенту }

else if kol_dvoek=0 then goto u

else Begin

writeln('студент ',fio,' группы ',namb,' является разгильдяем так как');

writeln('имеет в зимнюю сессию ',kol_dvoek,' двоек и является');

writeln('кандидатом на отчисление в весеннем семестре');

readln; end; end;

u: end; END.

Программа снабжена комментариями, поэтому при внимательном рассмотрении читается легко. Трудности могут возникнуть при разборе блока анализа результатов, поэтому мы приведем блок-схему логической части этого блока (рис. 9.1).