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;beginfor i:=1 to 5 doBegincase i of1: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) thenBegin writeln('введите правильно оценку'); goto M1; end;if oc[i,1]>2 then Begin oc[i,2]:=0; oc[i,3]:=0; goto M4; end elseM2: writeln('введите вторую оценку студента ',fio,' по ',predmet);readln(oc[i,2]);if (oc[i,2]<2) or (oc[i,2]>5) thenBegin writeln('введите правильно оценку'); goto M2; end;if oc[i,2]>2 then begin oc[i,3]:=0; goto M4; end elseM3: Writeln('введите третью оценку студента ',fio,' по ',predmet);readln(oc[i,3]);if (oc[i,3]<2) or (oc[i,3]>5) thenbegin 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 doo[k,l]:=0;writeln('введите оценки студентов ',fio);rea_ocenki(fio,o); end;end;end;{ конец ввода оценок студентов }{ отображение на экране введения оценок }for i:=1 to kgr dofor j:=1 to kst[i] doBegin with gr[i,j] doBegin for k:=1 to 5 dowrite(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] doBeginfor 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 beginwriteln('студент ',fio,' группы ', namb,' подлежит отчислению так как');writeln('имеет три двойки по предмету ',predmet);v:=1; readln; goto w; end { на новый предмет }else Begin kol_dvoek:=kol_dvoek+2; goto w; endelse Begin kol_dvoek:=kol_dvoek+1; goto w; end;w: end;if v=1 then goto u { к новому студенту }else if kol_dvoek=0 then goto uelse Beginwriteln('студент ',fio,' группы ',namb,' является разгильдяем так как');writeln('имеет в зимнюю сессию ',kol_dvoek,' двоек и является');writeln('кандидатом на отчисление в весеннем семестре');readln; end; end;u: end; END.Программа снабжена комментариями, поэтому при внимательном рассмотрении читается легко. Трудности могут возникнуть при разборе блока анализа результатов, поэтому мы приведем блок-схему логической части этого блока (рис. 9.1). |