1. Синтаксис и семантика языков программирования. Алфавит языка Delphi Pascal. Описание синтаксиса языка: синтаксические диаграммы. Примеры.

Синтаксис – правила, определяющие допустимые конструкции языка, построенные из символов его алфавита.

Семантика – правила, определяющие смысл синтаксически корректных предложений.

Алфавит языка программирования Delphi Pascal включает:

  1. латинские буквы без различия строчных и прописных + символ _ (считается как буква);
  2. арабские цифры;
  3. шестнадцатеричные цифры: 0..9, а..f или A..F;
  4. специальные символы: + - * / = := ; и т. д.;
  5. служебные слова.

Синтаксическая диаграмма – это направленный граф с одним входным ребром и одним выходным ребром и помеченными вершинами.

2. Представление данных в Delphi Pascal: константы и переменные. Классификация скалярных типов данных, операции над ними. Примеры.

Классификация типов данных языка

  1. Простой
    1. Порядковые
    1. Целые;
    2. Логические;
    3. Символ;
    4. Перечисление;
    5. Отрезок (Интервал);
    3. Вещественный
    1. Вещественные;
    2. Большое целое;

3. Совместимость типов данных и операции преобразования типов. Примеры.

По правилам совместимы:

  1. все целые типы между собой;
  2. все вещественные типы между собой;
  3. отрезок базового типа и базовый тип;
  4. два отрезка одного и того же базового типа;
  5. символ и строка.

Неявное преобразование типов

Если типы результата и переменной не совпадают, но совместимы, то при выполнении присваивания выполняется неявное автоматическое преобразование.

Явное преобразование типов

Для несовместимых типов результата и переменной, в которую его необходимо занести, при выполнении присваивания необходимо явное преобразование типов, например, посредством специальных функций:

4. Присваивание, условный оператор, оператор выбора. Синтаксис операторов, их особенности и примеры использования.

Присваивание :=

Используется для изменения значений переменных.
Формат: <идентификатор_переменной> := <выражение>;

Корректное выполнение оператора предполагает, что результат вычисления и переменная правой части одного типа или совместимы по типу.

Условный оператор if

Оператор условной передачи управления используется при обработке вариантов вычислений и реализует конструкцию ветвления.

Формат: if <логическое_выражение> then <оператор> [else <оператор>];

Оператором может быть как простой оператор, так и составной оператор (блок операторов в операторных скобках begin...end)

Оператор выбора case

Оператор позволяет программировать несколько вариантов решения.

Пример:

case 1 + 2 * j of
    3:         z:=sin(x);
    -1..1, 10: z:=cos(x);
    else       z:=0;
end;

5. Операторы циклов Delphi Pascal. Синтаксис операторов, их особенности и примеры использования.

Операторы организации циклов

Счётный цикл for-loop

Выполняется конкретное количество раз.
Формат:
for <переменная-счётчик> := <значение_от> to <значение_по> do <оператор>; (если от < по)
for <переменная-счётчик> := <значение_от> downto <значение_по> do <оператор>; (если от > по)

Пример:

var i: Integer;
{...}
for i := 1 to 10 do
    begin
        x := x + 1;
        e := e / 10;
    end;

Итерационные циклы

while-do

Выполняется, пока условие истинно.

Пример:

while abs(e) >= 1e-5 do
    begin
        x := x + 1;
        e := e / 10;
    end;

repeat-until

Выполняется, до тех пор, пока условие не станет истинно (то есть пока условие ложно).
Первый раз один проход цикла выполняется в любом случае.

Пример:

repeat
    x := x + 1;
    e := e / 10;
until abs(e) < 1e-5;

6. Поисковый цикл. Неструктурная и структурная реализации поискового цикла.

Поисковый цикл – особый вид цикла, который имеет два случая выхода:

  1. нашли,
  2. перебрали все элементы, но не нашли.

Неструктурная реализация поискового цикла

var
    found: boolean;

{...}
found := false;
while true do
    begin
        {операторы, выполняемые до проверки}
        
        if {проверка на то, нашли ли необходимое} then begin
                found := true;  // ставим флаг, что нашли
                break;          // прерываем цикл
            end;
        if {проверка на то, не перебрали ли всё} then
            break;
        
        {операторы, выполняемые после проверки}
    end;

if found then
    {нашли}
else
    {не нашли}

Структурная реализация поискового цикла №1 (через while-do)

var
    found: boolean;

{...}
{операторы, выполняемые до проверки}
found := {нашли ли необходимое};
while not (found) and not ({не перебрали ли всё}) do
    begin
        {операторы, выполняемые после проверки}
        {операторы, выполняемые до проверки}
        if {нашли ли необходимое} then
                found := true;  // ставим флаг, что нашли
    end;

if found then
    {нашли}
else
    {не нашли}

Структурная реализация поискового цикла №2 (через repeat-until)

Примерный общий вид структурной реализации поискового цикла:

var
    found: boolean;
{...}

found := false;
repeat
    {операторы, выполняемые после проверки}
    {операторы, выполняемые до проверки} // !!! 
                                         // тут отличается от первой структурной реализации:
                  // выполнится в первый раз в любой случае, в отличие от первой реализации!
    if {нашли ли необходимое} then
        found := true;                   // ставим флаг, что нашли
until (found) or ({всё перебрали});

if found then
    {нашли}
else
    {не нашли}

7. Массивы Delphi Pascal. Описание, операции над массивами и их элементами. Примеры.

Массив – это упорядоченная совокупность однотипных данных. Каждому элементу массива соответствует один или несколько индексов порядкового типа, определяющих положение элемента в массиве.

Формат: array [<типы индекса>] of <тип элемента> (типы индекса перечисляются через запятую, если их больше одного).

Количество типов индексов задает размерность массива.
Тип индекса – порядковый – определяет доступ к элементу.
Тип элемента – любой кроме файла, в том числе массивы, строки и т.п.
Массив в памяти не может занимать более 2 Гб (из-за технических ограничений).

Операции над массивами

  1. Операция присваивания (только для массивов одного типа)
  2. Доступ к элементу массива (прямой и косвенный доступ)
  3. Ввод/вывод массивов осуществляется поэлементно:

8. Строки Delphi Pascal. Описание, операции над строками и их элементами. Примеры.

Строка – последовательность символов (фактически, массив символов).

Формат (обычно): string или string[<размер>], где размер – максимальная длина строки.

Операции над строками

  1. Присваивание строк:
  2. Обращение к элементу:
  3. Конкатенация (сцепление) строк:
  4. Операции отношения – выполняется попарным сравнением кодов символов, результат определяется по отношению кодов первых различных символов:
  5. Ввод-вывод строк:

9. Множества Delphi Pascal. Описание, операции над множествами и их элементами. Примеры.

Множество – неупорядоченная совокупность неповторяющихся элементов.

Формат: set of <базовый_тип>.
Тип элементов – порядковый, но количество элементов не должно превышать 256. (То есть нельзя использовать Word, Integer, UInt64 и т. д., так как они явно больше 256)

Операции над множествами

  1. Присваивание.
  2. Объединение, пересечение и дополнение:
    • A + B (A∪BA \cup B) – объединение множеств А и B – множество, состоящее из элементов, принадлежащих множествам А и B.
    • A * B (A∩BA \cap B) – пересечение множеств А и B – множество, состоящее из элементов, принадлежащих одновременно и множеству А и множеству B.
    • A - B (A∖BA \setminus B) – дополнение множества А до B – множество, состоящее из тех элементов множества А, которые не принадлежат множеству B.
  3. Операции отношения:
    • A = B (A=BA = B) – проверка совпадения множеств А и B (если совпадают – true).
    • A <> B (A≠BA \not= B) – проверка не совпадения множеств А и B (не совпадают – true).
    • A <= B (A⊆BA \subseteq B) – проверка нестрогого вхождения A в B (если входит – true).
    • A > B (A⊃BA \supset B) – проверка строгого вхождения B в A (если входит – true).
  4. Проверка вхождения элемента во множество:
    x in A (x∈Ax \in A) – входит ли элемент x в множество A (если входит – true).

10. Записи Delphi Pascal. Описание, операции над записями и их элементами. Примеры.

Запись – это структура данных, образованная фиксированным числом разнотипных компонентов, называемых полями записи

type
    EntryType = (Book, Magazine);
    Entry = record
        autor, title: String;
        year : 1..2000;
        case tag: EntryType of
            Book: (publisher, city: String);
            Magazine: (
                magName: String; 
                volume, issue: Integer
            );            // case не имеет своего end'а и пишется последним.
    end;

Операции над записями

  1. Присваивание записей одного типа.
  2. Доступ к полям записи (точечная нотация, оператор доступа with).
  3. Ввод и вывод записей осуществляется по полям.

11. Процедуры и функции. Определение, описание, особенности. Примеры.

Процедуры и функции – самостоятельные фрагменты программы, соответствующим образом оформленные и вызываемые по имени (программные блоки).

Общий вид программного блока: Заголовок блока -> Раздел описаний -> Раздел операторов

Процедура

Заголовок начинается с служебного слова procedure.
После работы процедура не возвращает значений.

Функция

Заголовок начинается с служебного слова function и заканчивается возвращаемым типом. После работы функции, она возвращает значение типа, который указан в заголовке как возвращаемый.

Чтобы вернуть какое-то значение из функции, в процессе её выполнения необходимо присвоить системной переменной <идентификатор_функции> (или result, при включенном расширенном синтаксисе {$X+}) это необходимое значение.

12. Способы передачи данных в подпрограмму на Delphi Pascal. Примеры.

Подпрограмма может получать данные из основной программы:

  1. неявно – с использованием свойства доступности глобальных переменных;
  2. явно – через параметры.

Очевидно, что явная передача значительно лучше, так как позволяет делать подпрограммы более универсальными и независимыми.

Типы параметров

13. Локальные и глобальные переменные, законы «видимости» идентификаторов. Примеры.

Классы переменных Время жизни Доступность
Глобальные – объявленные в основной программе От запуска до завершения программы Из любого места программы, включая подпрограммы*
Локальные – объявленные в подпрограмме От вызова подпрограммы до возврата управления Из подпрограммы и подпрограмм, вызываемых из нее*

* – при отсутствии перекрытия имен

14. Формальные и фактические параметры подпрограмм Delphi Pascal. Примеры.

Параметры, описанные в заголовке – формальные.

При вызове подпрограммы необходимо определить фактические значения этих параметров – аргументы (константы и переменные).

Вот только кто вообще их так называет?
Обычно их называют параметрами и аргументами соответственно.

Формальные и фактические параметры должны соответствовать по количеству, типу и порядку:

15. Параметры-строки, параметры-массивы. Примеры.

Структурные типы параметров должны быть предварительно объявлены.

type
    IntArr = array[1..100] of Integer;
    MyStr = string[25];

function sum(arr: IntArr; n: Integer): integer;
{...}

procedure test_string(str: MyStr);
{...}

var
    my_arr: IntArr;
    my_str: MyStr;
    {...}

begin
    {...}
    writeLn('Sum(arr) = ', sum(my_arr, n));
    test_string(my_str);
end.

16. Принципы разработки универсальных подпрограмм: «открытые» массивы и строки. Примеры.

Открытые массивы

Открытый массив – конструкция описания типа массива без указания типа индексов.
Используется только при объявлении формальных параметров.

array of Single;
array of Integer;

С помощью открытых массивов можно делать более универсальные подпрограммы.

Индексы открытого массива всегда начинаются с 0-го.

Размер можно:

Открытые строки

Для строк, передаваемых в подпрограмму как параметр-переменная, осуществляет контроль длины строки.

Чтобы избежать его необходимо использовать «открытые» строки (openstring).

Устаревшая информация. В новых версиях проблем с передачей строк быть не должно.

17. Принципы разработки универсальных подпрограмм: нетипизированные параметры, параметры процедурного типа. Примеры.

Нетипизированные параметры.

Нетипизированные параметры – параметры-переменные, тип которых при объявлении не указан.

Для приведения нетипизированного параметра к определенному типу можно использовать:

  1. автоопределенное преобразование типов:

    procedure proc(var a);
    {...}
    b := Integer(a) + 10;
    
  2. наложенное описание переменной определенного типа:

    type
        TType = (TReal, TInteger);
    
    procedure proc(var a; t: TType);
    var
        r: Real absolute a;
        i: Integer absolute a;
    
    {...}
        if t = TReal then
            {используем переменную `r`}
        else
            {используем переменную `i`}
    

    По факту, тут a является ссылкой на какой-то адрес в памяти, но нужный размер в памяти нам неизвестен. С помощью наложения мы делаем несколько видов переменных, накладывая на адрес переменной a разные типы.

Параметры процедурного типа

Параметры процедурного типа используются для передачи в подпрограмму имен процедур и функций.

Для объявления процедурного типа используется заголовок подпрограммы, в котором отсутствует имя:

type
    Proc = procedure (a, b, c: Real; var d: Real);
    UnaryFunc = function(x: Double): Double;

Значениями переменных процедурных типов являются идентификаторы процедур и функций с соответствующими заголовками.

18. Структура модуля Delphi Pascal. Законы видимости идентификаторов. Доступ к «перекрытым» идентификаторам. Примеры.

Модуль – это автономно компилируемая коллекция программных ресурсов, предназначенных для использования другими модулями и программами

Структура модуля:

unit <имя_модуля>;  // Имя модуля должно совпадать с 
                    // именем файла, в котором он описан.

interface
    <интерфейсная_секция>

implementation
    <секция_реализации>

[initialization
    <секция_инициализации>

[finalization
    <секция_завершения>]]
end.

Законы видимости идентификаторов. Доступ к «перекрытым» идентификаторам

Ресурсы модуля перекрываются ресурсами программы и ранее указанных модулей.

Для доступа к перекрытым ресурсам модуля используют точечную нотацию: <имя_модуля>.<имя_ресурса>

Пример:
identificators_intersection

19. Рекурсия. Виды рекурсии. Особенности программирования. Достоинства и недостатки. Пример.

Рекурсия – организация вычислений, при которой процедура или функция обращаются к самим себе.

Различают явную и косвенную рекурсии.
При явной – в теле подпрограммы существует вызов самой себя, при косвенной – вызов осуществляется в подпрограммах, вызываемых из рассматриваемой.

Косвенная рекурсия требует предопределения forward.

20. Адресация динамической памяти: понятие адреса, операции получения адреса и разыменования. Процедуры получения памяти и освобождения ее. Примеры.

Минимальная адресуемая единица памяти – байт.

Физический адрес АфА_ф – номер байта оперативной памяти.

Адресация по схеме «база+смещение»: Аф=Аб+АсмА_ф = А_б + А_{см},
где АбА_б – адрес базы – адрес, относительно которого считают остальные адреса;
АсмА_{см} – смещение – расстояние от базового адреса до физического.

Указатель – тип данных, используемый для хранения смещений.
В памяти занимает 4 байта, адресует сегмент размером V=232=4V = 2^{32} = 4 ГБ.
Базовый адрес = адрес сегмента.

Различают указатели:

Операции с указателями

  1. Получение адреса: оператор @. Результат операции – указатель типа pointer – может присвоен любому указателю.
  2. Доступ к данным по указателю (операция разыменования). Полученное значение имеет тип, совпадающий с базовым типом данных указателя. Нетипизированные указатели разыменовывать нельзя.

Процедуры для работы с памятью

  1. Процедура new(var p: ^<тип>) – выделяет память для размещения переменной, размер определяется типом указателя.
  2. Процедура dispose(var p: ^<тип>) – освобождает выделенную память.
  3. Процедура getMem(var p: Pointer; size: Integer) – выделяет указанное количество памяти и помещает ее адрес в указатель.
  4. Процедура freeMem(var p: Pointer[; size: Integer]) – освобождает выделенную память.
  5. Процедура sizeOf(x): Integer – возвращает размер объекта в байтах.
    type
        ByteArr = array[1..100] of Byte;
    
    var
        buffer: ^ByteArr;
    
    {...}
    getMem(buffer, sizeOf(ByteArr));
    buffer^[1] := 125;
    {...}
    freeMem(buffer, sizeOf(Byte) * 100); 
    

21. Списковые структуры данных. Классификация и основные приемы работы с ними: создание элемента, добавление элемента к списку, удаление элемента из списка. Область применения списковых структур данных. Пример.

Список – способ организации данных, предполагающий использование указателей для определения следующего элемента.

Элемент списка состоит из двух частей: информационной и адресной.

Информационная часть содержит поля данных.
Адресная – включает от одного до n указателей, содержащих адреса следующих элементов. Количество связей, между соседними элементами списка определяет его связность: односвязные, двусвязные, n-связные.

Виды списков

22. Основы файловой системы: файл, каталог, дисковод, полное имя файла, внутреннее представление информации в файле. Файловая переменная. Операции открытия и закрытия файлов. Примеры.

Файл – поименованная последовательность элементов данных (компонентов файла), хранящихся, как правило, во внешней памяти.
Как исключение данные файла могут не храниться, а вводиться с внешних устройств (ВУ), например клавиатуры или выводиться на ВУ.
Полное имя файла включает:
<Имя диска>:<Список имен каталогов>\<Имя файла>.<Расширение>

Файл языка Pascal – последовательность однотипных компонентов: файл записей, файл целых чисел, файл строк.

В зависимости от типа компонентов различают три типа файлов: типизированные, текстовые и нетипизированные.

Количество компонентов файла при объявлении файловой переменной не указывается.
Максимальный размер файла определяется свободным пространством на устройстве, например, диске.
Физически операции ввода-вывода с файлами выполняются с использованием буфера.

Доступ к компонентам файла осуществляется через указатель файла.
При выполнении операции чтения или записи указатель автоматически перемещается на следующий компонент.
После вывода последнего компонента файла система пишет специальную запись – маркер «Конец файла» (байт #26).
При обнаружении во время операции чтения маркера конца файла – операция завершается. Попытка читать маркер вызывает прерывание по ошибке чтения.

Процедура assign или assignFile (var f; path: String) (предпочтительнее) – связывает файловую переменную f с файлом, имя которого указано в строке path.

Инициализация файловой переменной

Процедура assign или assignFile (var f; path: String) (предпочтительнее) – связывает файловую переменную f с файлом, имя которого указано в строке path.

Если файл находится в текущем каталоге, то достаточно задать имя файла и его расширение. В противном случае необходимо указать полное имя файла.

Открытие файла

При открытии файла необходимо задать направление передачи данных: запись или чтение. Кроме того текстовый файл можно открыть для добавления компонентов.

  1. Процедура reSet(var f) – открывает файл для чтения данных.
    Устанавливает указатель файла на первый компонент. Если файл не существует, выдается сообщение об ошибке.

  2. Процедура reWrite(var f) – открывает файл для записи.
    Если указанный файл существовал, то он уничтожается без выдачи предупреждения пользователю, иначе он создается и указатель устанавливается на начало.

  3. Процедура append(var f: Text) – открывает текстовый файл для добавления данных.
    Указатель файла устанавливается на конец файла.

Закрытие файла

Процедура close или closeFile(var f) - выполняет закрытие файла. При этом вновь созданный файл регистрируется в каталоге.

Процедура закрытия файла обеспечивает вывод оставшихся компонентов из буфера в файл.

Связь файловой переменной с файлом при закрытии сохраняется, поэтому при продолжении обработки повторно процедуру assignFile() можно не выполнять.

23. Текстовые файлы. Внутреннее представление информации в файле. Операции над файлами. Пример.

Текстовый файл – файл, компонентами которого являются символьные строки переменной длины, заканчивающиеся специальным маркером – маркером «Конец строки».

Текстовые файлы используют для хранения и обработки символов, строк, символьных массивов. Числовые и логические данные при записи в текстовые файлы должны преобразовываться в символьные строки.

Текстовый файл можно открыть для записи, чтения и добавления записей в конец. Файл, открытый для записи, не может использоваться для чтения и наоборот.

Операции с текстовыми файлами

  1. Функция EOLn([var f]): Boolean – возвращает TRUE, если во входном текстовом файле достигнут маркер конца строки; при отсутствии файловой переменной проверяется файл INPUT, связанный с клавиатурой.
    • При работе с клавиатурой функция EOLn возвращает TRUE, если последним считанным был символ #13.
    • При работе с диском функция EOLn возвращает TRUE, если следующим считанным будет символ #13.
  2. Процедура read([var f: text;] v1, v2, {...} vn)
  3. Процедура readLn([var f: text;] v1, v2, {...} vn)
  4. Процедура write([var f: text;] v1, v2, {...} vn)
  5. Процедура writeLn([var f: text;] v1, v2, {...} vn)
  6. Процедура seekEOLn([var f]): Boolean – пропускает пробелы и знаки табуляции до маркера конца строки или до первого значащего символа и возвращает TRUE, при обнаружении маркера.
  7. Процедура SeekEOF([var f]): Boolean – пропускает все пробелы, знаки табуляции и маркеры конца строки до маркера конца файла или до первого значащего символа и возвращает TRUE при обнаружении маркера.

24. Типизированные файлы: внутреннее представление информации в файле. Операции над файлами. Пример.

Типизированный файл – файл, все компоненты которого одного типа, заданного при объявлении файловой переменной.

Компоненты хранятся на диске во внутреннем (двоичном) формате.

Типизированный файл можно открыть для записи и чтения. Файл, открытый для записи, может использоваться для чтения. В файл, открытый для чтения, можно писать.

Поскольку размер компонентов одинаков, принципиально возможен не только последовательный, но и прямой доступ.

Процедуры и функции обработки типизированных файлов

  1. Процедура read(var f; c1, c2, {...} cn)
  2. Процедура write(var f; c1, c2, {...} cn)
  3. Процедура seek(var f; numcomp: LongInt)
  4. Функция fileSize(var f): LongInt
  5. Функция filePos(var f): LongInt
  6. Процедура truncate(var f) – выполняет «усечение» файла.

25. Нетипизированные файлы. Внутреннее представление информации в файле. Операции над файлами. Пример.

Нетипизированными называют файлы, объявленные без указания типа компонентов.

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

Нетипизированные файлы, как и типизированные, допускают организацию прямого доступа.
Нетипизированный файл можно открыть для записи и для чтения:

reSet(var f[; recsize: Word]);
reWrite(var f[; recsize: Word]);

где recsize – размер записи файла в байтах. Длину записи задают кратной 512 байт, например: 1024, 2048. Если длина записи не указана, она принимается равной 128.

Процедуры и функции обработки нетипизированных файлов

  1. Процедура blockRead(var f: file; var buf; count: Word[; var res: Word]) – осуществляет чтение блока записей из файла в буфер buf.
    Параметр res будет содержать количество фактически обработанных записей. Если последняя запись – неполная, то значение параметра res ее не учтет.

  2. Процедура blockWrite(var f: file; var buf; count: Word[; var res: Word]) – осуществляет запись блока из буфера buf в файл.

26. Классы консольного режима Delphi: описание классов, поля и методы, объявление объектов класса, доступ к полям и методам объекта, ограничение доступа. Пример.

Класс – это структурный тип данных, который включает описание полей данных, а также процедур и функций, работающих с этими полями данных.
C точки зрения синтаксиса класс – структурный тип данных, в котором помимо полей разрешается описывать прототипы (заголовки) процедур и функций, работающих с этими полями данных.

Применительно к классам такие процедуры и функции получили название методов.
Объект-переменная – переменная типа «класс».

var a: TRoom = (length: 3.5; width: 5.1);
Модификатор доступа Доступность
public поля и методы, доступны из других модулей
private поля и методы, доступны только в пределах модуля
protected поля и методы, доступны только в классах потомках
published поля и методы, видимы в инспекторе объектов

По умолчанию для всех полей используется модификатор public.

27. Классы консольного режима Delphi: Способы инициализация полей. Неявный параметр Self. Пример.

Любой метод неявно получает параметр self – ссылку (адрес) на поля объекта, и обращение к полям происходит через это имя.

function TRoom.square;
begin
    result := self.length * self.width;
End;

При необходимости эту ссылку можно указывать явно:

@self – адрес области полей данных объекта.

28. Процедурная и объектная декомпозиция. Диаграммы классов. Отношения между классами. Примеры.

Процедурная декомпозиция – процесс разбиения программы на подпрограммы.

Структурной называют декомпозицию, если:

Объектная декомпозиция – процесс представления предметной области задачи в виде отдельных функциональных элементов (объектов предметной области), обменивающихся в процессе выполнения программы входными воздействиями (сообщениями) .

  1. Наследование – механизм, позволяющий строить класс на базе более простого посредством добавления полей и определения новых методов.

    При этом исходный класс, на базе которого выполняется построение, называют родительским или базовым, а строящейся класс – потомком или производным классом.

    Если при наследовании какие-либо методы переопределяются, то такое наследование называется полиморфным.

  2. Композиция – механизм, позволяющий включать несколько объектов других классов в конструируемый.

  3. Наполнение (агрегация) – механизм, позволяющих включать указатели на объекты других классов в конструируемый.

29. Динамические объекты и объекты с динамическими полями в консольном режиме Delphi. Примеры.

var 
    a: TRoom; {объект А класса TRoom}
    b: array[1..5] of TRoom;  {массив объектов типа TRoom}

type pTRoom=^TRoom;  {тип указателя на объекты класса TRoom}

var  pC: pTRoom;  {указатель на объекта класса TRoom}

Для динамического объекта необходимо выделить память:

new(pC);

, а после его использования – освободить память:

dispose(pC);

Обращение к полям и методам аналогично доступу к полям записей:
Примеры:

v := a.length;
s := a.square;
s := s + b[i].square;
pC^.length := 3;

Создание полиморфных объектов:

Функция new(<тип_указателя>) – возвращает адрес размещенного и, возможно, сконструированного объекта. После необходим вызов конструктора.
Или new(<тип_указателя>, <конструктор>).

Деструктор – метод класса, который используется для корректного уничтожения полиморфного объекта, содержащего невидимое поле. Деструктор можно переопределять.

Уничтожение полиморфных объектов

Процедура dispose(<указатель>) – освобождает память, на которую указывает указатель. Перед вызовом процедуры необходим вызов деструктора, если он указан, и затем – выполняется освобождение памяти.
Или dispose(<указатель>, <деконструктор>).

program Ex_7_08;

{$APPTYPE CONSOLE}
uses
    SysUtils;

type
    pTRoomD = ^TRoomD;

    TRoomD = object
        length, width: Single;
        function square(): Single; virtual;
        constructor init(l, w: Single);
        destructor done;
    end;

type
    pTVRoomD = ^TVRoomD;
    TVRoomD = object(TRoomD)
        height: Single;
        function square(): Single; virtual;
        constructor init(l, w, h: Single);
    end;

function TRoomD.square;
begin
    result := length * width;
end;

constructor TRoomD.init;
begin
    length := l;
    width := w;
end;

destructor TRoomD.done;
begin
end;

constructor TVRoomD.init;
begin
    inherited init(l, w);
    height := h;
end;

function TVRoomD.square;
begin
    result := 2 * (inherited square() + height * (length + width));
end;

var
    pA: pTRoomD;
    pB: pTVRoomD;

begin
    {указатель базового типа, объект базового типа}
    pA := new(pTRoomD);
    pA^.init(3.5, 5.1);
    writeLn('Square =', pA^.square():6:2);  // `Square = 17.85`
    pA^.done();
    dispose(pA);

    {указатель производного типа, объект производного типа}
    pB := new(pTVRoomD);
    pB^.init(3.5, 5.1, 2.7);
    writeLn('Square =', pB^.square():6:2);  // `Square = 82.14`
    Dispose(pB, done);

    {указатель базового типа, объект производного типа}
    pA := new(pTVRoomD, init(3.5, 5.1, 2.7));
    writeLn('Square =', pA^.square():6:2);  // `Square = 82.14`
    dispose(pA, done);

    readLn;
end.

Динамические поля в объектах

program Ex_7_09;

{$APPTYPE CONSOLE}
uses
    SysUtils;

type
    pTRoomD = ^TRoomD;

    TRoomD = object
        length, width: Single;
        function square(): Single; virtual;
        constructor init(l, w: Single);
        destructor done; virtual;
    end;

type
    pTBRoomD = ^TBRoomD;

    TBRoomD = object(TRoomD)
        pB: pTRoomD;
        function square: Single; virtual;
        function BSquare: Single;
        constructor init(l, w: Single; lb, wb: Single);
        destructor done; virtual;
    end;

function TRoomD.square;
begin
    square := length * width;
end;

constructor TRoomD.init;
begin
    length := l;
    width := w;
end;

destructor TRoomD.done;
begin
end;

constructor TBRoomD.init;
begin
    inherited init(l, w);
    if (lb = 0) or (wb = 0) then
        pB := nil
    else
        pB := new(pTRoomD, init(lb, wb));
end;

function TBRoomD.BSquare;
begin
    if pB <> nil then
        BSquare := pB^.square
    else
        BSquare := 0;
end;

function TBRoomD.square;
begin
    square := inherited square() + BSquare();
end;

destructor TBRoomD.done;
begin
    if pB <> nil then
        Dispose(pB, done);
end;

var
    A: TBRoomD;
    pB1: pTBRoomD;
    pB2: pTRoomD;

begin
    {статический объект с динамическим полем}
    A.init(3.2, 5.1, 2.5, 1);
    writeLn(A.Square():6:2, A.BSquare():6:2);                // ` 18.82  2.50`
    A.done;
    
    {динамический полиморфный объект с динамическим полем}
    pB1 := new(pTBRoomD, init(3.2, 5.1, 2.5, 1));
    writeLn(pB1^.square():6:2, pB1^.BSquare():6:2);          // ` 18.82  2.50`
    dispose(pB1, Done);
    
    {динамический полиморфный объект с динамическим полем}
    pB2 := new(pTBRoomD, init(3.2, 5.1, 2.5, 1));
    writeLn(pB2^.square:6:2, pTBRoomD(pB2)^.BSquare():6:2);  // ` 18.82  2.50`
    dispose(pB2, done);
    
    readLn;
end.

30. Технология событийного программирования. События Windows, сообщения и события Delphi. Основные события Delphi. Примеры.

Приложение (в отличие от программы) – набор подпрограмм, вызываемых при наступлении некоторого события, которым считается любое изменение в системе, касающееся данного приложения.

События Delphi и их обработчики

Обработчики сообщений Windows предусмотрены у объектов класса TForm и классов управляющих компонентов, таких как кнопки, редакторы и т. п.

Обработка выполняется следующим образом:

  1. В системе происходит событие, например, пользователь передвинул мышь или нажал на клавишу клавиатуры, в результате генерируется сообщение об этом событии – сообщение Windows.
  2. Сообщение Windows диспетчируется конкретному приложению.
  3. В приложении сообщение передается активному компоненту (окну или управляющему элементу).
  4. Метод обработки сообщения Windows компонента инициирует заранее предусмотренные события Delphi.
  5. Если в приложении предусмотрен соответствующий обработчик события Delphi, то он вызывается, если нет – то продолжается обработка сообщения Windows.

События Delphi

Обработчики сообщений Windows, встроенные в классы компонентов VCL, инициируют множество событий Delphi.

Например, обработчик события клавиатуры WM_CHAR класса TForm инициирует три события Delphi.

enter image description here

Обработчики событий Delphi

Для каждого обработчика событий предусмотрен заголовок и определённый список передаваемых ему параметров.
procedure <компонент>.<Имя_компонента><Имя_события_delphi>(Sender: TObject[, {...}]);

  1. procedure TForm1.FormActivate(Sender:TObject);
    Параметр Sender – отправитель (инициатор события).
  2. procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
    Параметр Key – символ ANSI.
  3. procedure TForm1.Edit1KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
    Параметры: Key – виртуальный код, Shift – управляющие клав.
  4. procedure TForm1.Edit1KeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);

Примеры событий Delphi, обрабатываемые объектами класса TForm

  1. при изменении состояния формы:

    • OnCreate – в начальной стадии создания формы - используется при необходимости задания параметров (цвет или размер);
    • OnActivate – при получении формой фокуса ввода (окно становится активным и ему адресуется весь ввод с клавиатуры);
    • OnShow – когда форма (окно) становится видимой;
    • OnPaint – при необходимости нарисовать или перерисовать форму;
    • OnResize - при изменении размеров формы на экране;
    • OnDeactivate – при потере формой фокуса ввода (окно становится неактивным);
    • OnHide – при удалении формы с экрана (окно становится невидимым);
    • OnCloseQuery – при попытке закрыть форму - обычно используется для создания запроса-подтверждения необходимости закрытия окна;
    • OnClose – при закрытии формы;
    • OnDestroy – при уничтожении формы;
  2. от клавиатуры и мыши:

    • OnKeyPressed – при нажатии клавиш, которым соответствует код ANSI;
    • OnKeyDown, OnKeyUp – при нажатии и отпускании любых клавиш;
    • OnClick, OnDblClick – при обычном и двойном нажатии клавиш мыши;
    • OnMouseMove – при перемещении мыши (многократно);
    • OnMouseDown, OnMouseUp – при нажатии и отпускании клавиш мыши;
  3. при перетаскивании объекта мышью:

    • OnDragDrop – в момент опускания объекта на форму;
    • OnDragOver – в процессе перетаскивания объекта над формой (многократно);
  4. другие:

    • OnHelp – при вызове подсказки;
    • OnChange – при изменении содержимого компонент.