Записи с фиксированными частями
Записи с фиксированными частями называются так, потому, что в различных ситуациях имеют одинаковую структуру.
Например, запись "Личная карточка студента" может быть описана с помощью записи с фиксированными частями:
Type
student = record
family : string[20];
name : string[10];
patronymic : string[15];
year_birthday : integer;
number_of_group : integer; // Номер группы
Predmet1 : byte; // МатАнализ
Predmet2 : byte; // ИнжГрафика
Predmet3 : byte; // Химия
Predmet4 : byte; // Информатика
end;
Если поля несут одинаковую смысловую нагрузку, то их целесообразно объединить в отдельную структуру типа record.
Пример 11.1.
type student =record
family :string[20];
family : string[20];
name : string[10];
patronymic : string[15];
year_birthday : integer;
number_of_group : integer; // Номер групп
valuation =record // Оценки
Predmet1 : byte; // МатАнализ
Predmet2 : byte; // ИнжГрафика
Predmet3 : byte; // Химия
Predmet4 : byte; // Информатика
end;
end;
group = array[1..25] of student;
Var
group1, group2 : group;
Пример 11.2.
Type
valuation =record // Оценки
Predmet1 : byte; // МатАнализ
Predmet2 : byte; // ИнжГрафика
Predmet3 : byte; // Химия
Predmet4 : byte; // Информатика
end;
student = record
family : string[20];
name : string[10];
patronymic : string[15];
year_birthday : integer;
number_of_group : integer;
// Оценки за прошедший семестр
valuation_of_last_half_year : valuation;
end;
group = array[1..25] of student;
Var
group1, group2 : group;
Переменные типа record могут участвовать в операторах присваивания, но никакие операции над ними не допускаются. Арифметические или какие-либо другие операции могут выполняться только над отдельными полями записи.
К каждому из компонентов записи можно получить доступ, если использовать составное имя, то есть указать имя переменной, затем точку и имя поля.
Например, Client.name := “Mary”; или
Group1[1].family := “Ivanov”;
Для вложенных полей приходиться продолжать уточнения.
Например,
Group2[2]. Valuation_of_last_half_year.Predmet1 := 5;
11.2. Оператор WITH…DO
При совместной обработке нескольких полей записи можно воспользоваться оператором WITH…DO:
WITH <ПЕРЕМЕННАЯ> DO <ОПЕРАТОР>;
Здесь, WITH, DO – ключевые слова (с, делать);
<переменная> - имя переменной типа запись, за которым, возможно, следует список вложенных полей;
<оператор> - любой оператор TP.
Благодаря этому оператору пропадёт необходимость указывать при обращении к отдельному полю записи, кроме его собственного идентификатора ещё и идентификатор записи. Идентификатор записи указывается однократно в начале фрагмента программы обработки записи.
Например, вместо операторов
Client.name := “Mary”;
Client.family := “Ivanov”;
Client.year_birthday := 1986;
можем записать:
With Client do
Begin
name := “Mary”;
family := “Ivanov”;
year_birthday := 1986;
End;
Или, например, для заполнения массива, элементами которого являются записи:
For i := 1to ndo
Begin
With Group[i] do
Begin
Writeln (name);
Writeln (family);
Writeln (year_birthday);
With Valuation_of_last_half_year do
Begin
Writeln (Predmet1);
Writeln (Predmet2);
Writeln (Predmet3);
Writeln (Predmet4);
End;
End;
End;
Использование оператора WITH…DO даёт существенную экономию в размере программы.
Вариантные записи
Особой разновидностью записей являются записи с вариантами, которые объявляются с использованием зарезервированного слова CASE. Оператор CASE позволяет снизить избыточность информации. Так как все заданные варианты в вариантной части <накладываются> друг на друга, то есть каждому из них выделяется одна и та же область памяти.
С помощью записей с вариантами можем одновременно сохранять различные структуры данных, которые имеют большую общую часть, одинаковую во всех структурах, и небольшие отличающиеся части в различных структурах. То есть, записи с вариантами в различных ситуациях могут иметь разную структуру.
Описание типа <запись с вариантами> имеет следующий тип:
Type
Rec = record
{Описания фиксированных частей}
v1, v2 : Integer;
{Описание полей вариантной части}
case n : Word of
0 : (<Список полей – описаний переменных>);
1 : (<Список полей – описаний переменных>);
…
7 : (<Список полей – описаний переменных>);
end;
Здесь, описание включает вариантную часть, в которой используется оператор CASE. Описание завершается зарезервированным словом END. В качестве селектора используется идентификатор типа (n : Word). Переменная часть должна следовать после фиксированной части, если таковая имеется.
Например,
Type
Valuation1_of_last_half_year = record
Predmet1 : byte; // МатАнализ
Predmet2 : byte; // ИнжГрафика
Predmet3 : byte; // Химия
Predmet4 : byte; // Информатика
End;
Valuation2_of_last_half_year = record
Predmet5 : byte;
Predmet6 : byte;
Predmet7 : byte;
Predmet8 : byte;
End;
Student = record
{фиксированная часть записи}
family : string[20];
name : string[10];
patronymic : string[15];
year_birthday : integer;
number_of_group : integer; // Номер групп
{вариантная часть записи }
case half_year : byte of
1 : (val1 : Valuation1_of_last_half_year); { Оценки за 1-ый семестр}
2 : (val2 : Valuation2_of_last_half_year); { Оценки за 2-ой семестр}
end;
group = array[1..25] of student;
Var
group1, group2 : group;
Здесь, вариантная часть записи включает две части:
· обычная фиксированная часть;
· вариантная часть, состоящая из поля признака (поля тела).
Заполнение записи такого вида:
Fori := 1tondo begin
With group1[i] do
Begin
{Заполнение фиксированной части}
…..
{Заполнение вариантной части}
half_year := 1;
With val1 do
Begin
Predmet1 := 5;
Predmet2 := 2;
Predmet3 := 3;
Predmet4 := 4;
End;
End; End;
Оператор FillChar(Group1[i], SizeOf(Group[i]),’’); заполняет пробелами поля записи и используется для того, чтобы новые данные каждый раз помещались на чистое место.
Если этот оператор не использован, может возникнуть ситуация, когда в ответ на запрос о вводе строки в некоторое поле Вы нажмёте клавишу [Enter], а в поле останется старое содержимое. Именно это помогает избежать процедура FillChar().
Задача 11.1.Необходимо организовать хранение информации о студентах некоторого вуза так, чтобы по каждому студенту фиксировались 4 основные характеристики: имя, год рождения, адрес и успеваемость. Распечатать список студентов, фамилии которых начинаются с буквы «Г», и их оценки за всё время обучения.
Листинг программы
PROGRAM LAB10_SEVEN; {Запись в файл}
USES CRT;
TYPE NAME1 = RECORD N : STRING[10]; {имя студента}
FAM : STRING[10]; {фамилия студента}
END;
STR_ADD1 = RECORD HOUSENUM : INTEGER; {номер дома}
STREET : STRING[10]; {название улицы}
END;
ADDRESS1 = RECORD STR_ADD : STR_ADD1;
CITY : STRING[10]; {название города}
STATE : STRING[15]; {название страны}
ZIP : INTEGER; {индекс города}
END;
SUBJECT1 = RECORD
SUB : ARRAY[1..10] OF STRING[10]; {массив предметов}
BALL : ARRAY[1..10] OF INTEGER; {массив баллов}
M1 : INTEGER; {количество предметов}
END;
TEACH1 = RECORD
YEAR : STRING[4]; {год поступления в вуз}
SUBJECT : SUBJECT1; {предметы}
MIDDLE : REAL; {среднее значение}
END;
STUDENT1 = ARRAY[1..25] OF RECORD
NAME : NAME1;
YEARB : STRING[4];
ADDRESS : ADDRESS1;
TEACH : TEACH1;
END;
LIBFILE = FILE OF STUDENT1;
VAR S: STUDENT1;
G1 : STUDENT1;
F : LIBFILE;
N, I, J : INTEGER;
PROCEDURE ENTER;
VAR P : REAL;
BEGIN
ASSIGN (F,'E:\7\GFILE.DAT');
REWRITE (F);
WRITELN ('Введите количество студентов в группе <= 25');
READLN (N);
FOR I := 1 TO N DO BEGIN
WITH S[I] DO BEGIN
WITH NAME DO BEGIN
TEXTMODE(CO80); TEXTCOLOR(LIGHTBLUE);
WRITE ('Введите фамилию '); TEXTCOLOR(MAGENTA); GOTOXY(35,1);
READLN (FAM); TEXTCOLOR(LIGHTBLUE);
WRITE ('Введите имя '); TEXTCOLOR(MAGENTA); GOTOXY(35,2);
READLN (N); TEXTCOLOR(LIGHTBLUE);
END;
WRITE ('Введите год рождения '); TEXTCOLOR(MAGENTA); GOTOXY(35,3);
READLN (YEARB); TEXTCOLOR(LIGHTBLUE);
WITH ADDRESS DO BEGIN
WITH STR_ADD DO BEGIN
WRITE ('Введите номер дома '); TEXTCOLOR(MAGENTA); GOTOXY(35,4);
READLN (HOUSENUM); TEXTCOLOR(LIGHTBLUE);
WRITE ('Введите название улицы ');TEXTCOLOR(MAGENTA); GOTOXY(35,5);
READLN (STREET); TEXTCOLOR(LIGHTBLUE);
END;
WRITE ('Введите название города ');TEXTCOLOR(MAGENTA); GOTOXY(35,6);
READLN (CITY); TEXTCOLOR(LIGHTBLUE);
WRITE ('Введите название штата ');TEXTCOLOR(MAGENTA); GOTOXY(35,7);
READLN (STATE); TEXTCOLOR(LIGHTBLUE);
WRITE ('Введите номер индекса '); TEXTCOLOR(MAGENTA); GOTOXY(35,8);
READLN (ZIP); TEXTCOLOR(LIGHTBLUE);
END;
WITH TEACH DO BEGIN
WRITE ('Введите год поступления в ВУЗ '); TEXTCOLOR(MAGENTA); GOTOXY(35,9);
READLN (YEAR); TEXTCOLOR(LIGHTBLUE);
WITH SUBJECT DO BEGIN
WRITE ('Введите количество предметов '); TEXTCOLOR(MAGENTA); GOTOXY(35,10);
READLN (M1);
P := 0;
FOR J := 1 TO M1 DO BEGIN
TEXTCOLOR(LIGHTBLUE); GOTOXY (1,11); CLREOL;
WRITE ('Введите название предмета ');
TEXTCOLOR (MAGENTA); GOTOXY(40,11);
READLN (SUB[J]);
TEXTCOLOR(LIGHTBLUE); GOTOXY (1,12); CLREOL;
WRITE ('Введите результат последней сессии ');
TEXTCOLOR (MAGENTA); GOTOXY(40,12);
READLN (BALL[J]);
P := P + BALL[J];
END;
P := P / M1;
MIDDLE := P;
END; END; END;
WRITELN; END;
WRITE(F,S);
CLOSE (F);
TEXTCOLOR(LIGHTGRAY);
TEXTMODE(CO80+8*8);
END;
PROCEDURE EX;
VAR K, L, H : INTEGER;
BEGIN
H := 15;
RESET (F);
IF IORESULT <> 0 THEN BEGIN CLOSE (F); HALT; END
ELSE BEGIN WHILE NOT EOF (F) DO BEGIN
READ (F,G1);
END; END;
L := 10;
TEXTCOLOR (LIGHTBLUE); GOTOXY (1,1);
WRITELN ('Фамилия ');
WRITELN ('Имя');
WRITELN ('Дата рождения: ');
FOR I := 1 TO N DO BEGIN
WITH G1[I] DO BEGIN
IF NAME.FAM[1] = 'Ѓ' THEN BEGIN
WITH NAME DO BEGIN
TEXTCOLOR (MAGENTA);
GOTOXY (H + L,1); WRITELN (FAM);
GOTOXY (H + L,2); WRITELN (N);
END;
GOTOXY (H + L,3); WRITELN (YEARB);
L := L + 20;
WRITELN; END; END; END;
READKEY;
CLOSE (F);
END;
BEGIN
CLRSCR;
ENTER;
EX;
END.
Вопросы для самопроверки
1. Дайте определение записи?
2. Каков формат описания переменной типа запись в разделе описания переменных?
3. Где описывается поле записи?
4. Как называется запись, объявленная в разделе Var?
5. Каков формат описания переменной типа запись в разделе Var, при наличии вложенной записи?
6. В чём состоит отличие в описании записи, объявленной в разделе Type?
7. Как описать тип записи в разделе описания новых типов, при наличии вложенной записи?
8. Какой подход используют при описании переменной типа запись в разделе Var, при наличии нового типа записи?
9. Какой используют способ доступа к полям записи?
10. Как можно осуществить доступ к полям вложенной записи?
11. В чём состоит преимущество использования оператора With..do?
Лабораторная работа №11