Основы программирования — Осенний семестр; Михалкович С.С.; 2008; VII
Содержание
Записи
Введение
type <имя записи>= record
<поля записи>
end;
Поля записей
Инициализация записей при описании (на примере Student)
Доступ к полям записей. Точечная нотация.
Замечание. Для записей имеет место именная эквивалентность типов.
Передача записей в подпрограммы. Записи как возвращаемые значения функции
Передача записей в п/п (Print(s)). Запись как возвращаемое значение функции (s := ReadStudent;).
Передавать записи по значению неэффективно, т.к. копируются все поля. Поэтому следуют передавать их по ссылке (с ключевым словом const - если значения полей не изменяются, и var - если внутри п/п их требуется изменить.
Оператор with.
with <переменная типа запись> do
begin
<поле>:=<значение>
end;
Оператор удобен, когда нужно выполнить достаточное количество операций с одной и той же переменной (имя этой переменной и точка добавляются неявно перед всеми полями)
Методы в записях
На примере Student.Print.
Запись как пространство имен
Запись выступает для своих полей и методов в качестве модуля (поскольку является набором данных и связанных с ними процедур и функций, оформленных как единое целое).
Методы работают в некотором окружении, в роли которого выступают поля записи и другие методы.
Т.о. возникает понятие инкапсуляции:
- Инкапсуляция — хранение в записи одновременно данных и методов (запись представляет собой «капсулу»).
Инкапсуляция тесно связана с защитой данных: лишь некоторые члены в этой «капсуле» являются открытыми.
Создается окружение при описании переменной типа запись.
- Сравнение s.Print и Print(s)
s.Print - объектно-ориентированный подход, доминирует объект, который сам выполняет над собой действие.
Print(s) - процедурно-ориентированный подход, главным является действие, выполняющееся над переменной.
- Метод Init - инициализатор полей записи.
Лекция 23
Создание простейших графических объектов
RPoint = record x, y: integer end;
RRectangle = record p1,p2: RPoint end;
Для каждого типа определяются методы Print, Draw, MoveOn
Записи как средство упаковки параметров
Пример. Используем определенные типы записей для создания перегруженных версий процедур Rectangle и Line:
Rectangle(x1,y1, x2,y2: integer)
Rectangle(p1,p2: RPoint)
Rectangle(r: RRectangle)
Line(x1,y1, x2,y2: integer)
Line(p1,p2: RPoint)
Line(r: RRectangle)
Переменная типа запись как объект
В модуле можно выносить реализацию методов записи в раздел реализации. При этом в разделе интерфейса внутри определения типа запись описываются только заголовки методов, а в разделе реализации перед именем метода необходимо писать <Имя записи>.
Поля записи как состояние объекта.
Методы записи как действия, воздействующие на состояние объекта.
Методы делятся на две категории
- меняющие состояние объекта (MoveOn для RPoint)
- осуществляющие доступ к состоянию объекта на чтение (Draw для RPoint)
Сортировка массива записей.
Лекция 24
Индексная сортировка
Часто физически переставлять элементы массива или вообще невозможно, или долго (в силу достаточно большого размера, например). В этом случае удобно использовать перестановку индексов вместо перестановки самих элементов.
Идея заключается в том, чтобы описать индексный массив index, который взаимооднозначно сопоставляет реальным индексам элемента виртуальные таким образом, чтобы относительно виртуальных массив оказался упорядоченным.
Пример.
Дан массив целых (с реальными индексами):
5[1] 15[2] 3[3] 1[4] 9[5] 8[6] 20[7] 12[8]
А так выглядит отсортированный массив по виртуальным индексам:
1[1] 3[2] 5[3] 8[4] 9[5] 12[6] 15[7] 20[8]
Т.е.
index[1] = 4 index[2] = 3 index[3] = 1 index[4] = 6 index[5] = 5 index[6] = 8 index[7] = 2 index[8] = 7
Соответственно, алгоритм сортировки меняется таким образом, что вместо перемены местами самих элементов упорядочиваемого массива меняется содержимое элементов index.
Вначале удобно положить элементы index соответствующими тождественной подстановке (т.е. a[i] = i).
type CmpFunc = function (const s1,s2: Student): boolean;
procedure BubbleIndexStudentSort(const a: StArr; var Index: IArr; n: integer; Cmp: CmpFunc);
begin
for var i:=1 to n do
Index[i] := i;
for var i:=n downto 2 do
for var j:=1 to i-1 do
if Cmp(a[Index[j+1]],a[Index[j]]) then
Swap(Index[j+1],Index[j]);
end;
procedure WriteArrByIndex(const a: StArr; const Index: IArr; n: integer);
begin
for var i:=1 to n do
writeln(a[Index[i]].name,' ',a[Index[i]].course,' ',a[Index[i]].group);
end;
Статические методы записей
type RRectangle = record
class function EqualSquare(const r1,r2: RRectangle): boolean;
class function CreateRandom: RRectangle;
end;