Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Программирование. Процедурное программирование. Учебное пособие

.pdf
Скачиваний:
0
Добавлен:
07.09.2026
Размер:
2 Мб
Скачать
☆
Основные возможности процедурного программирования при работе с комбинированными данными…
станта. Элементы списка отделяются друг от друга точками с запятой. По­ля должны указываться в той последовательности, в которой они перечис­лены в объявлении типов.
Константы-записи
type TFraction = record {Запись "дробь"} Numerator, Denominator: Integer; {Числитель и знаменатель} end; TSetFraction = array[1..3] of TFraction; const // Константа типа TFraction Fr: TFraction = (Numerator: 1; Denominator:2); // Массив дробей: 1/2, 1/4, 1/8 Fractions: TSetFraction =((Numerator: 1; Denominator:2), (Numerator: 1; Denominator:4), (Numerator: 1; Denominator:8));
Значение типизированной константы-множества задается в виде пра-
вильного конструктора множества.
Константы-множества
type TDays = set of 1..31; TLetters = set of 'A'..'Z'; const Days: TDays = [1, 9, 17, 25]; Letters: TLetters = ['B'..'D','F'..'H','J'..'N'];
Преобразование типов
В Delphi данные одного типа могут быть преобразованы в данные
другого типа. Существует явное и неявное преобразование.
В случае явного преобразования типов вызываются специальные
функции преобразования, аргументы которых принадлежат к одному типу, а значения – к другому. Эти функции представлены в табл. 3.
Таблица 3
Функция Описание
Int
Возвращает целочисленную часть числа с плавающей точкой как число с плавающей точкой
Функции явного преобразования типов
Frac Возвращает дробную часть числа с плавающей запятой Trunc Возвращает целочисленную часть числа с плавающей точкой
71
Глава 2
Функция Описание
Round Округляет число с плавающей запятой до целого значения Ord Возвращает ASCII код символа Chr Возвращает значение символа по его ASCII коду
Примеры применения функций явного преобразования типов
var A, B: Integer; C: Char; X, Y: Real; begin X := Int(1.75); // В результате X равен 1.0 Y := Frac(1.75); // В результате Y равен 0.75 A := Trunc(1.75); // В результате A равен 1 B := Round(1.75); // В результате B равен 2 A := Ord('S'); // В результате A равен 83 C := Chr(75); // В результате C равен 'K' end.
Окончание табл. 3
В Delphi существует и более общий механизм преобразования типов,
который заключается в применении идентификатора типа как идентифика­тора функции преобразования к выражению преобразуемого типа.
Примеры явного преобразования типов
var A: Byte; C: Char; begin A := Byte('S'); // Аналог A := Ord('S'); C := Char(75); // Аналог C := Chr(75); end.
Неявное преобразование типов возможно в следующих случаях:
в выражениях, содержащих вещественные и целочисленные пе-
1)
ременные, последние преобразуются к вещественному типу, и все выраже­ние приобретает вещественный тип;
одна и та же область памяти трактуется как содержащая данные
2)
то одного, то другого типа.
Совмещение данных в памяти может произойти, например, при ис-
пользовании записей с вариантами.
72
Основные возможности процедурного программирования при работе с комбинированными данными…
Контрольные вопросы и задания
1. Как добавить запись в конец типизированного файла, в его начало
и середину?
Как осуществить сортировку типизированного файла?
2.
В чем состоит отличие типизированных от нетипизированных
3.
констант? Перечислите виды типизированных констант.
Что такое явное преобразование типов?
4.
В каких случаях происходит неявное преобразование типов?
5.
2.4. Обработка исключительных ситуаций. Создание отдельно компилируемых программ
Обработка исключительных ситуаций
Delphi расширяет язык Pascal наличием механизма обработки ис-
ключительных ситуаций (Exceptions). Использование механизма исключи­тельных ситуаций значительно облегчает написание приложения, устойчи­вого к ошибкам. Это дает возможность восстановить работу приложения после возникновения ошибки или выхода, если дальнейшее продолжение невозможно.
В качестве примера рассмотрим создание приложения, обрабаты-
вающего записи в файле. Для создания устойчивого к ошибкам приложе­ния должно быть выполнено множество проверок, например, входной файл должен проверяться на существование. Если выполняются вычисле­ния, то их результаты должны быть проверены на допустимость. Выпол­нение этих условий обычными методами языка Delphi требует разрыва ко­да проверками на ошибки, которые могут увести в сторону от нормального прохождения алгоритма. Исключительные ситуации обеспечивают средст­ва, отделяющие алгоритм от проверки на ошибки. Это упрощает код и об­легчает его чтение.
Исключительные ситуации являются индикатором ошибочных со-
стояний. Исключительная ситуация представляет собой сигнал, что где-то в приложении произошла ошибка. В Delphi исключительные ситуации реализованы как экземпляры объектов, содержащие информацию об ошибке и месте ее возникновения. Они генерируются (возбуждаются) в случае возникновения ошибки. После этого исключительная ситуация остается возбужденной до тех пор, пока не будет обработана или пока приложение не завершится. Следовательно, когда она возбуждена, прило­жение должно отреагировать на нее.
73
Глава 2
Для того чтобы приложение отреагировало на ту или иную ошибку,
исключительная ситуация должна произойти в охраняемом блоке кода, располагающемся внутри специального блока. Если в каком-то операторе этого блока происходит исключительная ситуация, то последующие опера­торы не выполняются. Вместо этого управление немедленно переходит на блок операторов реагирования, который выполняется для прекращения выполнения или для обработки исключительной ситуации.
Охраняемый блок и блок реагирования составляют то, что называют
защищенным блоком. Delphi имеет два типа защищенных блоков. Первый тип используется для задания реакции с кодом завершения.
Защищенный блок для задания реакции с кодом завершения
try
{ Охраняемый блок операторов }
finally
{ Блок реакции с кодом завершения}
end;
Второй тип защищенного блока используется для задания обработ-
чиков особых ситуаций.
Защищенный блок для задания обработчиков
исключительных ситуаций
try
{ Охраняемый блок операторов }
except
{ Блок реакции с обработчиками исключительной ситуации}
end;
Внутри части блока
except
создаются обработчики исключительных ситуаций для классов исключительных ситуаций. Каждая из них должна принадлежать к определенному классу.
Формат обработчика исключительной ситуации
on <Класс особой ситуации> do begin
{Код, обрабатывающий особую ситуацию} end;
Чтобы продемонстрировать создание обработчика исключительной ситуации, вернемся к функции TestFile (п. 2.3) проверки корректности за­данного файла. В приведенном коде использовались опция отключения
74
Основные возможности процедурного программирования при работе с комбинированными данными…
проверки ввода/вывода и обращение к функции IOResult. В новой версии процедуры проверки корректности файла, приведенной ниже, использует­ся обработка исключения EInOutError, которое генерируется при любой ошибке ввода/вывода. В этом случае переход осуществляется в блок обра­ботки этого исключения, в котором выводится сообщение и просьба ввести новое имя файла. После этого процедура вызывается повторно для нового имени файла.
Проверка корректности файла с помощью обработки
исключительных ситуаций
procedure TestFile(FileName: string); var FileIn: TextFile; begin
try {Охраняемые операторы} AssignFile(FileIn, FileName); Reset(FileIn); CloseFile(FileIn); except {Исключение EInOutError - ошибка ввода/вывода } on E: EInOutError do begin WriteLn('Файл ',FileName,' не существует!'); Write(' Повторите ввод: '); ReadLn(FileName); TestFile(FileName); end; end; end;
В табл. 4 приведены некоторые из существующих классов исключе­ний Delphi.
Класс
исключения Exception Базовый класс всех обработчиков исключительных ситуаций EMathError Исключительные ситуации для чисел с плавающей точкой
EInvalidOp
EZeroDivide
EOverflow
Исключительные ситуации, происходящие в том случае, когда мате­матическому сопроцессору передается ошибочная инструкция
Исключительная ситуация, которая вызывается в случае деления на ноль
Исключительная ситуация, которая вызывается при попытке выполнения операций, приводящих к переполнению вещественных переменных
Некоторые классы исключений в Delphi
Описание
Таблица 4
75
Глава 2
Класс
исключения
Окончание табл. 4
Описание
EUnderflow
EIntError Исключительные ситуации целочисленной математики
EDivByZero
ERangeError
EIntOverflow
EInOutError
EInvalidCast Исключительные ситуации приведения типов
EInOutError
Исключительная ситуация, происходящая как результат переполне­ния операций с плавающей точкой при слишком малых величинах
Исключительная ситуация, которая вызывается в случае деления на ноль
Исключительная ситуация, происходящая в случае присвоения значения элементу, выходящему за пределы допустимого диапазона. Например, при попытке обращения к элементам массива по индексу, выходящему за пределы массива
Исключительная ситуация, которая вызывается при попытке выпол­нения операций, приводящих к переполнению целых переменных
Исключительные ситуации ввода/вывода при включенной директиве {$I+}
Исключительные ситуации при выполнении функций StrToInt и StrToFloat, когда конвертация строки в соответствующий числовой тип невозможна
Создание отдельно компилируемых подпрограмм
Модулем называется отдельно компилируемая несамостоятельная часть программы, содержащая набор подпрограмм, типов данных и других определений, предназначенных для решения общего круга задач.
Необходимость создания модулей назрела с ростом объема кода про­грамм и развитием командной работы над общей задачей. Потребовалась поддержка на уровне языка в разнесении программного кода на несколько независимых фрагментов, которые можно было бы, во-первых, разрабаты­вать в параллельном режиме, а во-вторых, экспортировать и использовать в других программных продуктах. В модули часто помещают описание данных, наборы функций и процедур, решающих задачи некоторой общей предметной области.
В Delphi модули оформляются в виде отдельных файлов. Каждый модуль состоит из заголовка и некоторых разделов (частей). Заголовок мо-
unit
дуля содержит слово
и имя модуля. Имя модуля должно совпадать
с именем файла, содержащего модуль. Модуль заканчивается ключевым
end
словом
с точкой.
В качестве частей модуля выступают: интерфейсная часть, часть реализации, инициализирующая и финализирующая части.
76
Основные возможности процедурного программирования при работе с комбинированными данными…
Схематичная структура модуля такова:
unit MyUnit;
interface
{Интерфейсная часть: сюда помещаются все определения, необходимые для обмена с программой (подключение других модулей, константы, типы, переменные, заголовки процедур и функций).}
implementation
{Часть реализации: здесь описываются процедуры и функции, указанные в интерфейсной части модуля, и приводятся необходимые для этого определения.}
initialization
{Инициализирующая часть, содержащая операторы, выполняющиеся до начала выполнения основной программы (присвоение начальных значений, открытие файлов и т. д.).}
finalization
{Финализирующая часть, содержащая операторы, выполняющиеся после выполнения основной программы (закрытие файлов). Порядок операторов в этой части является обратным порядку соответствующих операторов инициализирующей части.}
end.
При наличии нескольких используемых модулей инициализирую­щие и финализирующие части выполняются в порядке подключения мо­дулей.
В зависимости от назначения некоторые части модуля, например инициализирующая и финализирующая части, могут быть опущены.
Для использования модуля его следует подключить в разделе
uses
основной программы, возможно подключение нескольких модулей через запятую. При этом возможно указание полного пути к файлу, содержаще­му этот модуль.
После того как модуль подключен, в основной программе становятся доступны перечисленные в его интерфейсной части объявления, и их мож­но использовать. При наличии одинаковых идентификаторов в основной программе и в модуле последние вызываются с использованием составно­го идентификатора, начинающегося с имени модуля, за которым через точку следует требуемый идентификатор.
В Delphi текст модуля сохраняется в файле с расширением .pas, тогда как код основной программы (основной файл проекта) хранится в тексто­вом файле с расширением .dpr.
77
Глава 2
Пример программы № 10
Разработать модуль, содержащий необходимые типы данных, про­цедуры и функции для поддержки вычислений с комплексными числами, позволяющие выполнять сложение, умножение и деление чисел, находить модуль числа, выводить число на экран в алгебраической форме.
Разработка программы
Из курса алгебры известно, что комплексное число содержит дейст­вительную и мнимую части, т. е. является парой чисел. Для хранения ком­плексного числа потребуется объявить специальный тип данных, позво­ляющий хранить логически связанные значения как одно целое. Объявим тип данных TCNumber c вещественнозначными полями Re и Im и помес­тим его объявление в интерфейсной части разрабатываемого модуля ComplexCalc.
unit ComplexCalc; interface type
TCNumber = record Re, Im: Real; end; ...
Поместим заголовочные части подпрограмм, требуемых по заданию, также в интерфейсную часть модуля после объявления типа.
procedure Add(C1, C2: TCNumber; var C3: TCNumber); procedure Subtract(C1,C2: TCNumber; var C3: TCNumber); procedure Multiply(C1, C2: TCNumber; var C3: TCNumber); procedure Divide(C1, C2: TCNumber; var C3: TCNumber); function Modul(C: TCNumber): Real; procedure Print(C: TCNumber);
Процедура Add выполняет сложение C1 и C2 по правилу сложения комплексных чисел и результат помещает в C3. Процедура Subtract вычис­ляет разность, Multiply выполняет умножение чисел, Divide – деление, а функция Modul вычисляет для числа C его модуль. Полный код этих подпрограмм в соответствии со структурой модуля поместим в его части реализации. Так же поступим и с процедурой Print, выполняющей вывод числа на экран в алгебраической форме, т. е. в виде (Re + i*Im). Реализация всех этих подпрограмм элементарная и дополнительного объяснения не
78
Основные возможности процедурного программирования при работе с комбинированными данными…
требует, единственное замечание можно сделать относительно вывода числа: нужно рассмотреть два случая, когда мнимая часть положительная и когда отрицательная, и в зависимости от этого выводить либо знак +, ли­бо –. Полностью код модуля приводится в листинге 10.1.
В качестве демонстрации работы с модулем напишем программу, за­прашивающую от пользователя ввод двух комплексных чисел и вычис­ляющую их сумму, разность, произведение, частное и модуль. Для этого подключим модуль (uses ComplexCalc), объявим три переменные C1, C2, C3 типа TCNumber, в основном теле программы выведем приглашение ко вводу данных, считаем числа и поместим их в соответствующие поля за­писей C1 и C2. Далее, используя объявленные в модуле подпрограммы, выполним вышеперечисленные операции над комплексными числами, ре­зультат выведем на экран. Текст программы приведен в листинге 10.2.
Листинг 10.1. Модуль ComplexCalc (файл ComplexCalc.pas)
unit ComplexCalc; interface type
TCNumber = record Re, Im: Real; end;
procedure Add(C1, C2: TCNumber; var C3: TCNumber); procedure Subtract(C1,C2: TCNumber; var C3: TCNumber); procedure Multiply(C1, C2: TCNumber; var C3: TCNumber); procedure Divide(C1, C2: TCNumber; var C3: TCNumber); function Modul(C: TCNumber): Real; procedure Print(C: TCNumber);
implementation
procedure Add(C1,C2: TCNumber; var C3: TCNumber); begin
C3.Re := C1.Re + C2.Re; C3.Im := C1.Im + C2.Im;
end;
procedure Subtract(C1,C2: TCNumber; var C3: TCNumber); begin
C3.Re := C1.Re - C2.Re; C3.Im := C1.Im - C2.Im;
end;
procedure Multiply(C1,C2: TCNumber; var C3: TCNumber); begin
C3.Re := C1.Re * C2.Re - C1.Im * C2.Im;
79
Глава 2
C3.Im := C1.Re * C2.Im + C1.Im * C2.Re;
end;
procedure Divide(C1, C2: TCNumber; var C3: TCNumber); begin
C3.Re := (C1.Re * C2.Re + C1.Im * C2.Im)/(C2.Re * C2.Re + C2.Im * C2.Im); C3.Im := (C1.Im * C2.Re - C1.Re * C2.Im)/(C2.Re * C2.Re + C2.Im * C2.Im);
end;
function Modul(C: TCNumber): Real; begin
Result := Sqrt(C.Re * C.Re + C.Im * C.Im);
end;
procedure Print(C: TCNumber); begin
if C.Im >= 0 then WriteLn(C.Re:6:2, ' + i *', C.Im:6:2) else WriteLn(C.Re:6:2, ' - i *', -C.Im:6:2)
end; end.
Листинг 10.2. Основной модуль (файл Example10.dpr)
program Example10;
{$APPTYPE CONSOLE}
uses SysUtils, Windows, ComplexCalc; var C1, C2, C3: TCNumber; begin SetConsoleOutputCP(1251); WriteLn('Вводите через пробел действительную и мнимую части комплексных чисел.'); Write('Введите первое число:'); Read(C1.Re); Readln(C1.Im); Write('Введите второе число:'); Read(C2.Re); Readln(C2.Im); Write('Сумма чисел:'); Add(C1, C2, C3); Print(C3); Write('Разность чисел:'); Subtract(C1, C2, C3); Print(C3); Write('Произведение чисел:');
80
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]