Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Программирование. Процедурное программирование. Учебное пособие
.pdf
Основные возможности процедурного программирования при работе с комбинированными данными…
станта. Элементы списка отделяются друг от друга точками с запятой. Поля должны указываться в той последовательности, в которой они перечислены в объявлении типов.
Константы-записи
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
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
