
Типизированные файлы
Типизированный файл – это файл, в котором содержатся однотипные данные. Типизированный файл задается с помощью 2-х ключевых слов «file of». После слова «of» указывается тип файла, например integer, real, char, string и т.д. Тип файла может быть любым за исключением файлового типа (не может быть файла файлов) и комбинированного типа, один из компонентов которого имеет файловый тип.
В отличие от текстовых файлов, в типизированном файле информация хранится в двоичном представлении (в текстовом файле информация хранится в виде цепочки символов). Данный факт позволяет производить чтение и запись в файл более быстрым способом, т.к. отсутствует необходимость в преобразовании данных. Кроме того, в типизированном файле возможен прямой доступ к записям файла (в текстовом файле возможен только последовательный доступ).
<Объявление файловой переменной для типизированного файла> ::=
var
<Имя переменной>: file of <тип>;
Процедуры и функции для работы с типизированными файлами (TP7)
procedure Assign(var F: File);
procedure Close (var F: File);
procedure Reset (var F: File);
Открывает существующий файл на чтение и запись. Маркер файла становится перед записью номер 0. Нумерация компонент начинается с нуля.
procedure Rewrite (var F: File);
Открывает файл на чтение и запись. Маркер файла становится перед записью номер 0. Файл после открытия имеет размер 0. Если файл ранее существовал, его содержимое теряется.
procedure Seek(var F: File, RecordNumber: Longint);
Перемещает маркер файла на компонент с номером RecordNumber. Нумерация компонент начинается с нуля.
procedure Truncate(var F: File);
Удаляет все компоненты файла, стоящие после маркера файла.
procedure Read(var F: File; <Список ввода>);
Читает из файла N компонент, где N – число пунктов в <Списке ввода>. Маркер файла перемещается вперед на N компонент.
procedure Write(var F: File; <Список вывода>);
Зписывает в файл N компонент, где N – число пунктов в <Списке ввода>. Маркер файла перемещается вперед на N компонент.
function Eof(var F: File): boolean;
Синтаксис Delphi:
procedure AssignFile(var F: <Файловый тип>; <Имя файла>: string);
procedure CloseFile (var F: <Файловый тип>);
Билет №24
Тип «Указатель»
<Тип «Указатель»> : : =
^<Тип> ;
<Тип «Указатель»> : : =
pointer ;
Тип «Указатель» используется для объявления переменной, которая должна содержать адрес некоторого набора данных в оперативной памяти. Таким адресом может быть либо адрес первого байта уже существующей переменной, либо адрес первого байта нового набора данных, создаваемого специально для этого предназначенной процедурой.
Существует специальное значение для указателя, имеющее имя Nil. Если указатель равен Nil, это означает, что он ни на что не указывает. Если указатель не инициализирован, нет гарантии, что он равен именно Nil.
Пример.
program P0801;
type
pInteger = ^integer ;
ppInteger = ^pInteger ;
pppInteger = ^ppInteger ;
var
p_i: ^integer ; // Аналогично p_i: pInteger ;
p_b: ^boolean ;
p_c: ^char ;
p: pointer ;
c: char ;
b: boolean ;
i: integer ;
begin
Writeln('sizeof(p)=', sizeof(p)) ;
Writeln('sizeof(b)=', sizeof(b)) ;
Writeln('sizeof(i)=', sizeof(i)) ;
Writeln('sizeof(c)=', sizeof(c)) ;
Readln;
b:=false ;
Writeln(b) ;
p_b := @b ; // p_i := @b ;
p := p_b ;
p_i := p ;
p_i^ := 7 ;
Writeln(b) ;
c:='A' ;
Writeln(c) ; { 'A' }
p_c := @c ;
p := p_c ;
p_i := p ;
p_i^ := p_i^ + 7 ;
Writeln(c) ; { 'H' }
Readln ;
end.
Билет №25
Тип pChar
Фактически:
type
pChar = ^Char;
Тип pChar предназначен для работы со строковыми данными в формате “Zero Terminated Strings” («Строки с нулевой концовкой»). Указатель типа pChar содержит адрес «первого» байта (символа) строки. Правда, нумерацию символов принято начинать не с единицы, а с нуля. Признаком конца строки служит символ с кодом 0 (#0). Последним символом строки будет тот, сразу после которого расположен символ #0.
Строки “Zero Terminated Strings” имеют и другое название:
ASCIIZ–строки.
Пример
var
mC: array[0..11] of char;
begin
mC[0] := ‘N’; mC[1] := ‘o’; mC[2] := ‘v’; mC[3] := ‘e’; mC[4] := ‘m’;
mC[5] := ‘b’; mC[6] := ‘e’; mC[7] := ‘r’;
mC[8] := #0; // mC[8] := Chr(0);
StrPCopy(mC, ‘November’);
end.
Процедура StrDispose
procedure StrDispose(SP: PChar);
Удаляет из динамической памяти строку. Строка размещается в динамической памяти функцией StrNew.
SP – удаляемая строка.
Если SP = nil, процедура ничего не выполняет.
Функция StrCat
function StrCat(Dest, Source: PChar): PChar;
Присоединяет к концу строки Dest строку Source. Результат – объединенная строка. Размер полученной строки не контролируется. Dest – первая строка; Source – вторая строка.
Функция StrComp
function StrComp(SPl, SP2: PChar): Integer;
Сравнивает две строки (символы сравниваются слева направо своими кодами). Результат меньше нуля, если первая строка меньше второй, равен нулю, если строки равны, и больше нуля, если первая строка больше второй.
Функция StrCopy
function StrCopy(Dest, Source: PChar): PChar;
Копирует строку Source в строку Dest. Возвращает в качестве результата новую строку Dest.
Source – копируемая строка;
Dest – строка для копирования.
Размер полученной строки не контролируется.
Функция, StrECopy
function StrECopy(Dest, Source: PChar): PChar; Копирует строку Source в строку Dest. Возвращает в качестве результата указатель на последний (нулевой) элемент строки.
Source – копируемая строка;
Dest – строка для копирования.
Размер полученной строки не контролируется.
Функция StrEnd
function StrEnd(SP: PChar): PChar;
Получает указатель на конец строки SP (на завершающий нулевой элемент).
SP – исходная строка.
Функция StrlComp
function StrLComp(SPl, SP2: PChar): PChar;
Сравнивает строки SPl и SP2 без различия между прописными и строчными латинскими буквами. Результат такой же, что и у функции StrComp.
SPl, SP2 – сравниваемые строки.
Функция StrLCat
function StrLCat(Dest,Source: PChar; MaxLen: Word): PChar;
Добавляет в конец строки Dest MaxLen символов строки Source. Если размер
строки Source меньше MaxLen, копируется фактическое количество символов. В
качестве результата возвращает объединенную строку.
Dest – первая строка;
Source – копируемая строка;
MaxLen – число копируемых символов.
Размер полученной строки не контролируется.
Функция StrLComp
function StrLComp(SPl, SP2: PChar; MaxLen: Word): PChar;
Сравнивает MaxLen первых символов строк SPl и SP2. Если размер строк меньше MaxLen, сравнивается фактическое количество символов. Результат такой же, что и у функции StrComp.
SPl, SP2 – сравниваемые строки;
MaxLen – число сравниваемых символов.
Функция StrLCopy
function StrLCopy(Dest, Source; PChar; MaxLen: Word): PChar;
Копирует MaxLen символов строки Source в строку Desi. Если размер строки Source меньше MaxLen, копируется фактическое число символов. Результат – скопированная строка.
Dest – строка для копирования;
Source – колируемая строка;
MaxLen – число копируемых символов.
Размер полученной строки не контролируется.
Функция StrLen
function StrLen(SP: PChar): Word;
Определяет размер строки без учета заключительного символа с кодом 0.
SP – исследуемая строка.
Функция StrLIComp
function StrLIComp(SPl, SP2: PChar; MaxLen: Word): PChar;
Сравнивает MaxLen первых символов строк SPl и SP2 без различия между прописными и строчными латинскими буквами. Если размер строк меньше MaxLen, сравнивается фактическое число символов. Результат такой же, что и у функции StrComp.
SPl,SP2 – сравниваемые строки;
MaxLen – число сравниваемых символов.
Функция StrLower
function StrLower(SP: PChar): PChar;
Преобразует в строке SP прописные латинские буквы в строчные. Результат –преобразованная строка.
SP – преобразуемая строка.
Функция StrMove
function StrMove(Dest, Source: PChar; Count: Word): PChar;
Копирует Count символов строки Source в строку Dest, даже если это число больше размера строки Source. Результат – скопированная строка.
Dest – первая строка;
Source – вторая строка. Размер полученной строки не контролируется.
Функция StrNew
function StrNew(SP: PChar): PChar;
Создает в динамической области копию строки SP. Результат – указатель на новую строку. Удаляется строка процедурой StrDispose.
SP – копируемая строка.
Функция StrPas
function StrPas(SP: PChar): string;
Преобразует ASCIIZ–строку в строку типа string. Результат – преобразованная строка.
SP – исходная строка.
Функция StrPCopy
function StrPCopy(Dest: PChar; Source: string): PChar; Преобразует строку Source типа string в ASCHZ–строку Dest. Результат – указатель на преобразованную строку.
Source – преобразуемая строка;
Dest – преобразованная строка.
Размер полученной строки не контролируется.
Функция StrPos
function StrPos(SPl, SP2: PChar): PChar;
Ищет первое вхождение строки SP2 в строку SPl. Результат – указатель на первое вхождение строки SP2 в строку SPl – либо nil, если такого вхождения нет.
SPl – строка, в которой ищется вхождение строки SP2;
SP2 – искомая строка.
Функция StrRScan
function StrRScan(SP: PChar; Chr: Char): PChar;
Ищет последнее вхождение символа Chr в строку SP. Результат – указатель на найденный символ либо nil, если такого символа нет.
SP – строка, где ищется символ;
Chr – искомый символ.
Функция StrScan
function StrScan(SP: PChar; Chr: Char): PChar;
Ищет первое вхождение символа Chr в строку SP Результат – указатель на найденный символ либо nil, если такого символа нет.
SP – строка, где ищется символ;
Chr – искомый символ.
Функция StrUpper
function StrUpper(SP: PChar): PChar;
Преобразует в строке SP строчные латинские буквы в прописные. Результат – преобразованная строка.
SP – преобразуемая строка.
Билет №26
Ключи компиляции (директивы компилятора)
Ключ компиляции задает режим компиляции программы. Этот режим управляет синтаксическими требованиями к исходному тексту программы, а также поведением откомпилированного кода программы.
Ключ является глобальным, если в модуле он может присутствовать только в одном месте – в начале модуля. Режим, задаваемый глобальным ключом, действует на весь модуль.
Ключ является локальным, если в модуле он может присутствовать во многих местах. Режим, задаваемый локальным ключом, действует на тот участок кода, который предшествует прямо противоположному ключу.
Выравнивание полей записей и классов
{$A+}, {$A-}, {$A1}, {$A2}, {$A4}, or {$A8}
или
{$ALIGN ON}, {$ALIGN OFF}, {$ALIGN 1}, {$ALIGN 2}, {$ALIGN 4},
or {$ALIGN 8}
По умолчанию:
{$A8}
или
{$ALIGN 8}
Зона действия: Локальный
Полное вычисление логических выражений
{$B+} or {$B-}
или
{$BOOLEVAL ON} or {$BOOLEVAL OFF}
По умолчанию:
{$B-}
или
{$BOOLEVAL OFF}
Зона действия: Локальный
Пример
x := 3;
{$B-}
if
(x > 4) // Вычисляется
and
(x < 5) // НЕ вычисляется
then . . . ;
Использование длинных строк (AnsiString)
{$H+} or {$H-}
или
{$LONGSTRINGS ON} or {$LONGSTRINGS OFF}
По умолчанию:
{$H+}
или
{$LONGSTRINGS ON}
Зона действия: Локальный
Проверка результата ввода-вывода
{$I+} or {$I-}
или
{$IOCHECKS ON} or {$IOCHECKS OFF}
По умолчанию:
{$I+}
или {$IOCHECKS ON}
Зона действия: Локальный
Разрешение использовать типизированные константы как переменные
{$J+} or {$J-}
или
{$WRITEABLECONST ON} or {$WRITEABLECONST OFF}
По умолчанию:
{$J-}
или
{$WRITEABLECONST OFF}
Зона действия: Локальный
Генерация информации о текущих типах полей, методов, свойств, объявленных в секции Published (RTTI, RunTime Type Information)
{$M+} or {$M-}
или
{$TYPEINFO ON} or {$TYPEINFO OFF}
По умолчанию:
{$M-}
или
{$TYPEINFO OFF}
Зона действия: Локальный
Если класс объявлен в режиме {$M-}, или не является потомком класса, объявленного в режиме {$M+}, секция Published запрещена.
Задание размера стека
{$M <Число: Мин. размер стека>, < Число: Макс. размер стека>}
или
{$MINSTACKSIZE <Число>}
{$MAXSTACKSIZE <Число>}
По умолчанию:
{$M 16384, 1048576}
Зона действия: Глобальный
1024 ≤ <Число: Мин. размер стека> ≤ 2147483647
<Число: Мин. размер стека> ≤ <Число: Макс. размер стека> ≤ 2147483647
Проверка выхода за пределы диапазона
{$R+} or {$R-}
или
{$RANGECHECKS ON} or {$RANGECHECKS OFF}
По умолчанию:
{$R-}
или
{$RANGECHECKS OFF}
Зона действия: Локальный
Пример. TP7
var
i: integer;
mA, nB: array[1..10] of integer;
begin
for i := 1 to 10 do begin mA[i] := 0; mB[i] := 0; end;
{$R-}
i := 12;
mA[i] := -7;
writeln(mA[i]); // -7
writeln(mB[2]); // -7
{$R+}
mA[i] := -7; // RunTime Error
writeln(mA[12]); // Constant Out Of Range
end.
Проверка переполнения при арифметических операциях
{$Q+} or {$Q-}
или
{$OVERFLOWCHECKS ON} or {$OVERFLOWCHECKS OFF}
По умолчанию:
{$Q-}
или
{$OVERFLOWCHECKS OFF}
Зона действия: Локальный
Пример. TP7
var
L: integer;
begin
L := 2000000000;
{$Q-}
L := L*L; // Реакции на переполнение нет
writeln(L); // -1651507200
L := 1000000000;
{$Q+}
L := L*L; // RunTime Error
end.
Разрешение использовать расширенный синтаксис
{$X+} or {$X-}
или
{$EXTENDEDSYNTAX ON} or {$EXTENDEDSYNTAX OFF}
По умолчанию:
{$X+}
или
{$EXTENDEDSYNTAX ON}
Зона действия: Глобальный
Пример 1. TP7
{$X+}
var
p: pChar; // То же, что p = ^Char;
const
mC: array[0..39] of char = 'Petrov'#0; // Синтаксическая ошибка при {$X-}
begin
// Во ВСЕХ последующих операторах
// будет выявлена синтаксическая ошибка при ключе {$X-}
// При ключе {$X+} код нормально компилируется и работает.
p := 'Nikolaev';
writeln(Ord(p[8])); // 0
writeln(p);
p := @mC;
writeln(p);
writeln(p[0]);
end.
Пример 2. TP7
{$X+}
uses crt;
var
c: char;
x, y: double;
begin
c := readkey;
ReadKey; // Синтаксическая ошибка при {$X-}
x := pi/2; y := sin(x);
sin(x); // Синтаксическая ошибка в любом случае
end.
Пример 3. Delphi
{$X+}
function Factorial(N: longint): longint;
var i: longint;
begin
Result := 1; // Синтаксическая ошибка при {$X-}
for i := 2 to N do Result := Result * i; // Синтаксическая ошибка при {$X-}
end;
Условная компиляция
{$define <Имя режима>} // Режим “<Имя режима>” включен
{$undef <Имя режима>} // Режим “<Имя режима>” выключен
{$ifdef <Имя режима>}
<Фрагмент кода 1>
// Выполняется только если режим “<Имя режима>” включен
{$else}
<Фрагмент кода 2>
// Выполняется только если режим “<Имя режима>” выключен
{$endif}
{$ifndef <Имя режима>}
<Фрагмент кода 2>
// Выполняется только если режим “<Имя режима>” выключен
{$else}
<Фрагмент кода 1>
// Выполняется только если режим “<Имя режима>” включен
{$endif}
Билет №27
Объектно-ориентированное программирование (ООП)
Понятие класса – дополнение к понятию типа.
Тип [обычной] переменной определяет множество значений, которые она способна принимать, и множество операций, которые над ней можно производить.
Класс [объектной] переменной определяет и множество значений, которые она способна принимать, и множество операций, которые над ней можно производить, и множество операций, которые она сама над собой способна производить.
Три принципа ООП:
Инкапсуляция
Наследование
Полиморфизм
Инкапсуляция – соединение в единой структуре данных и программных кодов (т.н. методов), предназначенных для обработки именно этих данных.
Наследование – возможность построения нового класса на основе существующего (т.н. базового, или родительского) класса с дополнением и/или переопределением данных и методов. Наследование есть механизм передачи данных и методов родительского класса в дочерний класс.
Полиморфизм – возможность обращения по одному имени к разным методам.
Объектом, или объектной переменной принято называть конкретный экземпляр переменной заданного класса.
По сути (но не по синтаксису), объектная переменная есть указатель на первый байт области памяти, выделенной под поля объекта. Эта область памяти предоставляется объекту тогда, когда он «начинает жить», и высвобождается тогда, когда он свою жизнь завершает.
Вместе с «рождением» первого экземпляра объекта заданного класса в память загружается и его инкапсулированные программные коды. Второй и последующие экземпляры, занимая под свои поля новые области памяти, пользуются уже загруженным кодом первого экземпляра.
Три группы атрибутов объекта:
Методы
Свойства
События
Методы – процедуры и функции, описываемые при описании класса, предназначенные для приема объектом данных извне, изменения данных внутри объекта (модификации полей), подачи данных от объекта внешним «потребителям».
Свойства (для пользователя объекта) – параметры (числовые, символьные, строковые и прочих типов), характеризующие состояние объекта в данный момент. Обращение к свойствам объекта внешне выглядит как обращение к полям переменной типа «запись».
Свойства (для программиста класса) – процедуры и функции, назначение которых совпадает с назначением методов. В среде программистов не утихают споры о праве свойств на существование.
События – это то, что с объектом «может произойти», и на что можно предусмотреть реакцию кода класса.
Объявление класса
<Имя класса> = class(<Имя базового класса>)
private
<Объявление закрытых полей и методов>
// Все, что объявлено здесь, может быть использовано только в данном модуле
protected
<Объявление открытых полей и методов>
// Все, что объявлено здесь, может быть использовано
// и в данном модуле, и во всех классах-наследниках данного класса
public
<Объявление открытых полей и методов>
// Все, что объявлено здесь, может быть использовано везде, где виден класс
published
<Объявление открытых полей и методов>
// видно в Инспекторе объектов
end;
Всё, что объявлено в разделе published, может быть использовано везде, где виден класс.
Раздел published может присутствовать, только если включен режим «динамическая идентификация типа данных» (Run-time type information, Run-time type identification, RTTI), который позволяет определить тип данных переменной или объекта во время выполнения программы.
Режим RTTI должен быть включен с помощью ключа {$M+}.
Билет №28
Конструктор
Объявление:
constructor TList1.Create;
begin
inherited Create;
// inherited;
pHead := Nil;
pTail := Nil;
nItems := 0;
end;
Обращение:
MyList1 := TList1.Create;
Обращение происходит к методу класса.
Деструктор
Объявление:
destructor TList1.Destroy;
begin
inherited Destroy;
// inherited;
end;
Обращение:
MyList1.Destroy;
Обращение происходит к методу объекта.
Дополнительно о полиморфизме
Как уже говорилось, каждый класс может иметь несколько конструкторов и
несколько деструкторов. Правила языка Delphi этого не запрещают. Однако, сре-
ди программистов есть разные точки зрения на то, следует ли разрешать исполь-
зовать несколько конструкторов и деструкторов.
Ниже приводится фрагмент текста для модуля Unit1.pas, в котором преду-
смотрено два деструктора.
В разделе интерфейса имеется два заголовка процедуры destructor. Наличие
двух заголовков сопровождается словами «overload» после них.
destructor Destroy; overload;
destructor Destroy(sFileName: string); overload;
Списки формальных параметров у заголовков должны быть такими, чтобы
не было «двусмысленности», т.е. чтобы компилятор мог однозначно определить
по списку фактических параметров, какой из двух разных кодов для процедуры с
одним именем следует применить.
Билет №29
Граф. Основные понятия и определения
Граф,
или неориентированный
граф
– это упорядоченная
пара
,
для которой выполнены следующие условия:
– это
непустое множество
вершин, или
узлов,
– это
множество пар (в случае неориентированного
графа – неупорядоченных) вершин,
называемых рёбрами.
(а значит и, , иначе оно было бы мультимножеством) обычно считаются конечными множествами. Многие хорошие результаты, полученные для конечных графов, неверны (или каким-либо образом отличаются) для бесконечных графов. Это происходит потому, что ряд соображений становится ложным в случае бесконечных множеств.
Вершины
и рёбра графа называются также элементами
графа, число вершин в графе
– порядком,
число рёбер
– размером
графа.
Вершины
и
называются концевыми
вершинами (или просто концами)
ребра
.
Ребро, в свою очередь, соединяет
эти вершины. Две концевые вершины одного
и того же ребра называются соседними.
Два ребра называются смежными, если они имеют общую концевую вершину.
Два ребра называются кратными, если множества их концевых вершин совпадают.
Ребро называется петлёй, если его концы совпадают, то есть .
Степенью
вершины
называют количество инцидентных ей
рёбер(при этом петли считают дважды).
Вершина называется изолированной, если она не является концом ни для одного ребра; висячей (или листом), если она является концом ровно одного ребра.
Ориентированный граф
Ориентированный
граф (сокращённо орграф)
– это упорядоченная
пара
,
для которой выполнены следующие условия:
– это непустое множество вершин или узлов,
– это множество (упорядоченных) пар различных вершин, называемых дугами или ориентированными рёбрами.
Дуга
– это упорядоченная пара вершин
,
где вершину
называют началом, а
– концом дуги. Можно сказать, что дуга
ведёт от вершины
к вершине
.
Билет №30 - 32
Динамические структуры данных
Линейный однонаправленный список
procedure AppendItem(sName: string; Salary: double);
procedure InsertItem(sName: string; Salary: double);
{$F+}
{$N+}
uses Crt, Strings;
type
pPersonType = ^PersonType;
PersonType = record
sName: string[40];
Salary: double;
pNext: pPersonType;
end;
var
pHead, pTail, pCurr: pPersonType;
function CompareItems(pCurr1,pCurr2: pPersonType): integer;
var
. . .
begin
. . .
end;
function AloneItem(sName: string; Salary: double;
var pNew: pPersonType): boolean;
begin
New(pNew);
if pNew = Nil then Halt;
pNew^.sName := sName;
pNew^.Salary := Salary;
pNew^.pNext := Nil;
if pHead=Nil then
begin
pHead := pNew; pTail := pNew; AloneItem := true;
end
else
AloneItem := false;
end;
procedure AppendItem(sName: string; Salary: double);
var
pNew: pPersonType;
begin
if not AloneItem(sName, Salary, pNew) then
begin
pTail^.pNext := pNew;
pTail := pNew;
end;
end;
procedure PrependItem(sName: string; Salary: double);
var
pNew: pPersonType;
begin
if not AloneItem(sName, Salary, pNew) then
begin
pNew^.pNext := pHead;
pHead := pNew;
end;
end;
Билет №33
Параметры без типа
{$X+}
{$N+} (* Только для TP7 *)
program Project2;
var
i: integer;
d: double;
s: string[2];
procedure ShowInteger(var x);
begin
writeln(Integer(x));
end;
procedure ShowDouble(var x);
begin
writeln(Double(x));
end;
procedure ShowString(var x);
begin
writeln(String(x));
end;
Билет №34
Процедурные типы
<Объявление типа «Процедура» > :: =
<Имя Типа> = procedure(<Список формальных параметров>) ;
<Объявление типа «Функция» > :: =
<Имя Типа> = function(<Список формальных параметров>): <Тип> ;
После объявления процедурного (или «функционального») типа можно объявлять переменные такого типа. Этим переменным можно будет присваивать «имена» уже описанных процедур или функций, а затем обращаться к ним по имени процедурной переменной.
На деле переменные процедурных типов являются указателями. До инициализации они имеют непредсказуемое значение. Не следует надеяться, что это именно Nil. Ответственность за вызов процедуры, на которую «указывает» неинициализированная процедурная переменная, несёт программист.
Билет №35
Оператор выбора
< Оператор выбора> ::=
case <Выражение-селектор> of
<Список 1> :
<Оператор 1> ;
<Список 2> :
<Оператор 2> ;
. . .
<Список N> :
<Оператор N> ;
else
<Операторы> ;
End
Записи с вариантной частью
type
MyTagType0 = (Type00, Type01, Type02, Type03);
MyTagType01 = (Type010, Type011, Type012, Type013);
MyTagType02 = (Type020, Type021, Type022, Type023);
MyRecordType1 = record
i: integer; d: double;
case Tag0: MyTagType0 of
Type00:
(
s: string[7];
mA: array[1..3] of single;
);
Type01:
(
R1, R2: MyRecordType2D;
);
Type02 .. Type03:
(
c1: char;
T1: TDateTime;
);
end;
MyRecordType2 = record
r: single;
case Tag0: MyTagType0 of
Type00:
(
bWas: boolean; mC: array[1..4] of char;
case Tag01: MyTagType01 of
Type010: (k: integer;);
Type011 .. Type013: (b: byte;);
);
Type01:
(
R1, R2: MyRecordType2D;
case Tag02: MyTagType02 of
Type020: (c: char;);
Type021 .. Type023: (s0: shortint;);
);
end;
Билет №36
Типизированные файлы
<Объявление файловой переменной для типизированного файла> ::=
var
<Имя переменной>: file of <тип>;
Процедуры и функции для работы с типизированными файлами (TP7)
procedure Assign(var F: File);
procedure Close (var F: File);
procedure Reset (var F: File);
Открывает существующий файл на чтение и запись. Маркер файла становится перед записью номер 0. Нумерация компонент начинается с нуля.
procedure Rewrite (var F: File);
Открывает файл на чтение и запись. Маркер файла становится перед записью номер 0. Файл после открытия имеет размер 0. Если файл ранее существовал, его содержимое теряется.
procedure Seek(var F: File, RecordNumber: Longint);
Перемещает маркер файла на компонент с номером RecordNumber. Нумерация компонент начинается с нуля.
procedure Truncate(var F: File);
Удаляет все компоненты файла, стоящие после маркера файла.
procedure Read(var F: File; <Список ввода>);
Читает из файла N компонент, где N – число пунктов в <Списке ввода>. Маркер файла перемещается вперед на N компонент.
procedure Write(var F: File; <Список вывода>);
Зписывает в файл N компонент, где N – число пунктов в <Списке ввода>. Маркер файла перемещается вперед на N компонент.
function Eof(var F: File): boolean;
Синтаксис Delphi:
procedure AssignFile(var F: <Файловый тип>; <Имя файла>: string);
procedure CloseFile (var F: <Файловый тип>);
Процедуры аналогичны соответственно процедурам Assign и Close.
Билет №37
Свойство (Property)
Свойство, как и поле класса, задает атрибут объекта. Но если поле есть просто хранилище данных, то свойство есть механизм обращения к данным и, возможно, механизм изменения данных. Свойство ограничивает доступ к данным теми рамками, которые задает программист.
Объявление:
public
property <Имя свойства>: <Тип>
read <Имя функции или поля для чтения> // Может отсутствовать, если есть write
write <Имя процедуры для модификации> // Может отсутствовать, если есть read
;
Пример. Delphi
TList1 = class(TObject)
private
pHead: pPersonType;
nItems: integer;
procedure DeleteTail(pFirstInTail: pPersonType);
public
function ItemsCountR: integer;
procedure ItemsCountW(k: integer);
property ItemsCount: integer read ItemsCountR write ItemsCountW;
end;
procedure TList1.DeleteTail(pFirstInTail: pPersonType);
var
pCurr, pDelete: pPersonType;
begin
pCurr := pFirstInTail;
while pCurr <> Nil do
begin
pDelete := pCurr;
pCurr := pCurr^.pNext;
Dispose(pDelete);
end;
end;
function TList1.ItemsCountR: integer;
var
pCurr: pPersonType;
n: integer;
begin
// ItemsCountR := nItems;
pCurr := pHead;
n := 0;
while pCurr <> Nil do
begin
Inc(n);
pCurr := pCurr^.pNext;
end;
nItems := n;
ItemsCountR := n;
end;
procedure TList1.ItemsCountW(k: integer);
var
pCurr, pPrev: pPersonType;
n: integer;
begin
// nItems := k;
if k < 0 then
begin
writeln(‘k must be non-negative!’);
Exit;
end;
pCurr := pHead;
n := 0;
while (pCurr <> Nil) and (n < k) do
begin
Inc(n);
pPrev := pCurr;
pCurr := pCurr^.pNext;
end;
if n < k then
begin
writeln(‘k must be less or equal to ’, n:0, ‘ !’);
Exit;
end;
pPrev^.pNext := Nil;
if pCurr <> Nil then
DeleteTail(pCurr);
nItems := k;
end;
Обращение к свойствам объекта:
Writeln(<Имя объектной переменной>.ItemsCount);
// Обращение к свойству “read”.
<Имя объектной переменной>.ItemsCount := 7;
// Обращение к свойству “write”.
Пример
var
MyList: TList1;
…
writeln(MyList1.ItemsCount);
writeln(MyList1.ItemsCountR);
…
MyList1.ItemsCount := 10;
MyList1.ItemsCountW(10);
Билет №38
Алгоритм Дейкстры (Dijkstra’s algorithm) – алгоритм на графах, изобретённый нидерландским ученым Э. Дейкстрой в 1959 году. Находит кратчайшее расстояние от одной из вершин графа до всех остальных. Алгоритм работает только для графов без рёбер отрицательного веса. Алгоритм широко применяется в программировании и технологиях, например, его использует протокол OSPF для устранения кольцевых маршрутов.
Дан
взвешенный ориентированный граф
без петель и дуг отрицательного веса.
–
множество вершин,
–
множество рёбер графа.
Требуется
найти кратчайшие пути от некоторой
вершины a графа
до всех остальных вершин этого графа.
Каждой
вершине
из
сопоставим метку – минимальное
известное расстояние до этой вершины
от начальной вершины
.
Алгоритм работает пошагово – на
каждом шаге он «посещает» одну вершину
и пытается уменьшать метки. Работа
алгоритма завершается, когда все вершины
посещены.
Инициализация. Метка начальной вершины полагается равной 0, метки остальных вершин – бесконечности. Это отражает то, что расстояния от до других вершин пока неизвестны. Все вершины графа помечаются как непосещённые.
Шаг алгоритма. Если все вершины посещены, алгоритм завершается. В противном случае, из ещё не посещённых вершин выбирается вершина , имеющая минимальную метку. Мы рассматриваем всевозможные маршруты, в которых является предпоследним пунктом. Вершины, в которые ведут рёбра из , назовем соседями этой вершины. Для каждого соседа вершины , кроме отмеченных как посещённые, рассмотрим новую длину пути, равную сумме значений текущей метки и длины ребра, соединяющего с этим соседом. Если полученное значение длины меньше значения метки соседа, заменим значение метки полученным значением длины. Рассмотрев всех соседей, пометим вершину как посещенную и повторим шаг алгоритма.
Пример
Рассмотрим выполнение алгоритма на примере графа, показанного на рисунке. Пусть требуется найти расстояния от 1-й вершины до всех остальных.
Кружками обозначены вершины, линиями – пути между ними (ребра графа). В кружках обозначены номера вершин, над ребрами обозначена их «цена» – длина пути. Рядом с каждой вершиной красным обозначена метка – длина кратчайшего пути в эту вершину из вершины 1.
Первый шаг. Рассмотрим шаг алгоритма Дейкстры для нашего примера. Минимальную метку имеет вершина 1. Её соседями являются вершины 2, 3 и 6.
Первый по очереди сосед вершины 1 – вершина 2, потому что длина пути до неё минимальна. Длина пути в неё через вершину 1 равна сумме кратчайшего расстояния до вершины 1, значению её метки, и длины ребра, идущего из 1-ой в 2-ую, то есть 0 + 7 = 7. Это меньше текущей метки вершины 2, бесконечности, поэтому новая метка 2-й вершины равна 7.
Аналогичную операцию проделываем с двумя другими соседями 1-й вершины – 3-й и 6-й.
Все соседи вершины 1 проверены. Текущее минимальное расстояние до вершины 1 считается окончательным и пересмотру не подлежит (то, что это действительно так, впервые доказал Э. Дейкстра). Вычеркнем её из графа, чтобы отметить, что эта вершина посещена.
Второй шаг. Шаг алгоритма повторяется. Снова находим «ближайшую» из непосещенных вершин. Это вершина 2 с меткой 7.
Снова пытаемся уменьшить метки соседей выбранной вершины, пытаясь пройти в них через 2-ю вершину. Соседями вершины 2 являются вершины 1, 3 и 4.
Первый (по порядку) сосед вершины 2 – вершина 1. Но она уже посещена, поэтому с 1-й вершиной ничего не делаем.
Следующий сосед вершины 2 – вершина 3, так как имеет минимальную метку из вершин, отмеченных как не посещённые. Если идти в неё через 2, то длина такого пути будет равна 17 (7 + 10 = 17). Но текущая метка третьей вершины равна 9<17, поэтому метка не меняется.
Ещё
один сосед вершины 2 – вершина 4. Если
идти в неё через 2-ю, то длина такого пути
будет равна сумме кратчайшего расстояния
до 2-ой вершины и расстояния между
вершинами 2 и 4, то есть 22 (7 + 15 = 22). Поскольку
22<
,
устанавливаем метку вершины 4 равной
22.
Все соседи вершины 2 просмотрены, замораживаем расстояние до неё и помечаем её как посещенную.
Третий шаг. Повторяем шаг алгоритма, выбрав вершину 3. После её «обработки» получим такие результаты:
Дальнейшие шаги. Повторяем шаг алгоритма для оставшихся вершин. Это будут вершины 6, 4 и 5, соответственно порядку.
Завершение выполнения алгоритма. Алгоритм заканчивает работу, когда вычеркнуты все вершины. Результат его работы виден на последнем рисунке: кратчайший путь от вершины 1 до 2-й составляет 7, до 3-й – 9, до 4-й – 20, до 5-й – 20, до 6-й – 11.
const
maxn = 100;
infinity = maxlongint;
var
i,j,u,v,n,m,c,min,s,t:longint;
e,w:array[1..maxn,1..maxn]of longint;
ne,use,p,d:array[1..maxn]of longint;
begin
read(n,m,t,s);
for i:=1 to m do begin
read(u,v,c);
inc(ne[v]); e[v,ne[v]]:=u; //edges are inverted
w[v,u]:=c;
end;
for i:=1 to n do d[i]:=infinity;
d[s]:=0;
for i:=1 to n do begin
min:=infinity;
for j:=1 to n do if (use[j]=0)and(d[j]<min) then begin
min:=d[j]; u:=j;
end;
use[u]:=1;
for j:=1 to ne[u] do begin
v:=e[u,j];
if d[v]>d[u]+w[u,v] then begin
d[v]:=d[u]+w[u,v]; p[v]:=u;
end;
end;
end;
writeln(d[t]);
u:=t; write(u);
while u<>s do begin
u:=p[u]; write(' ',u);
end;
end.
Билет №39
События мыши и клавиатуры
Особый интерес представляют события, происходящие с мышью и с клавиатурой в тот момент, когда указатель мыши нацелен на графический элемент управления класса TImage.
Пусть имя графического элемента – ImageGraph, имя формы – Form1.
Событие «нажата кнопка мыши» (MouseDown).
procedure TForm1.ImageGraphMouseDown(Sender: TObject;
Button: TMouseButton; Shift: TShiftState; x, y: Integer);
Sender: объект–предок объекта, с которым произошло событие. Из этого объекта можно «выудить» наиболее общие для визуальных элементов управления на форме свойства и методы. Например:
ShowMessage(Sender.UnitName);
повлечёт появление на экране ExtCtrls – имя модуля (устройства, юнита), в котором класс TObject объекта Sender объявлен.
Другой пример:
ShowMessage(Sender.Name);
повлечёт ошибку на этапе компиляции. Нет у объекта Sender свойства Name.
Button: параметр перечисляемого типа, объявленного в модуле Controls:
type
TMouseButton = (mbLeft, mbRight, mbMiddle);
По именам возможных значений параметра понятно, какая из кнопок мыши нажата.
Shift: параметр, имеющий тип–множество, объявленный в модуле Classes:
type
TShiftState = set of (ssShift, ssAlt, ssCtrl, ssLeft, ssRight, ssMiddle, ssDouble);
Тип TShiftState используется обработчиками событий мыши и клавиатуры для выяснения состояния клавиш Alt, Ctrl, Shift клавиатуры и кнопок мыши в момент происхождения события.
Составляющие множество «флаги» имеют следующий смысл:
ssShift – клавиша Shift нажата.
ssAlt – клавиша Alt нажата.
ssCtrl – клавиша Ctrl нажата.
ssLeft – левая кнопка мыши нажата.
ssRight – правая кнопка мыши нажата.
ssMiddle – средняя кнопка мыши нажата.
ssDouble – мышь получила двойной щелчок.
x, y: координаты указателя мыши (в пикселях) относительно верхнего левого угла элемента, с которым произошло событие (в данном случае, ImageGraph).
Событие «перемещается указатель мыши» (MouseMove).
procedure TForm1.ImageGraphMouseMove(Sender: TObject;
Shift: TShiftState; x, y: Integer);
Параметры в дополнительных пояснениях не нуждаются
Событие «отпущена кнопка мыши» (MouseUp).
procedure TForm1.ImageGraphMouseUp(Sender: TObject;
Button: TMouseButton; Shift: TShiftState; x, y: Integer);
Параметры в дополнительных пояснениях не нуждаются.
Ссылки на модули Controls и Classes должны присутствовать в предложении uses.