Лабораторная работа №9 (2 часа)



 

Обработка исключительных ситуаций

 

Цель: освоить технологию обработки исключительных ситуаций в среде Delphi.

Оборудование: ПЭВМ IBM PC-AT.

Программные средства: ОС семейства Windows, среда Delphi 5.* (или выше).

 

Задание

 

Разработать приложение, генерирующее и обрабатывающее исключения на основе варианта задания, согласованного с преподавателем. Вариант задания определить на основе следующего списка.

1. Создать программу, позволяющую пользователю ввести два числа, для выполнения операции деления. Необходимо поместить на форму три объекта класса TEdit – два для операндов, один – для результата и кнопку (объект класса TButton), нажимая на которую пользователь выполняет деление. Исключить попытку деления на ноль, а так же введения символов вместо цифр. Выдать сообщение о типе возникшей ошибке.

2. Создать программу, вычисляющую корни квадратного уравнения (ax2+bx+c=0). Необходимо поместить на форму четыре объекта класса TEdit – три для коэффициентов квадратного уравнения, один – для результата и кнопку (объект класса TButton), нажимая на которую пользователь выполняет нахождение корней. Исключить ввод символов вместо цифр, получение отрицательного дискриминанта и ввод а = 0. Вывести при всех типах ошибок одно и то же сообщение.

3. Создать программу с "бесконечным" циклом типа while. В цикле увеличивать переменную i до значения, заданного пользователем. При достижении этого значения выходить из цикла с помощью возбуждения исключения EAbort. Выдать сообщение о выходе из цикла в блоке Except. Необходимо поместить на форму кнопку (объект класса TButton), которая запускает цикл; сообщение можно выдать с помощью функции ShowMessage, или поместить на форму метку (объект класса TLabel), в которую помещается сообщение.

4. Создать программу, вычисляющую тангенс угла. Необходимо поместить в форму два компонента TEdit для ввода значения и результата и кнопку TButton для вычисления значения тангенса. Исключить ввод символов вместо цифр и получение значения тангенса угла 90 градусов. Предусмотреть возможность ввода значений в радианах.

5. Создать программу, вычисляющую логарифм числа. Для этого необходимо поместить в форму два компонента TEdit для ввода значения и результата и кнопку TButton для вычисления значения логарифма. Исключить ввод символов вместо цифр и получение значения логарифма 0.

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

 

Программа работы

 

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

2. В соответствии с заданием определить перечень предопределенных исключений Delphi для использования в своем приложении.

3. Разработать приложение, обрабатывающее исключительную ситуацию, согласно варианту индивидуального задания.

4. Запустить разработанное приложение и смоделировать ситуацию для возникновения исключения.

5. Проверить правильность запрограммированной реакции приложения.

6. Выявить и исправить ошибки.

7. Продемонстрировать результаты выполнения работы преподавателю.

 

Пояснения к работе

 

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

Дополнительный фактор возникновения исключительных ситуаций содержится в данных, с которыми работают программы. Традиционный способ корректной обработки исключительных ситуаций состоит в создании многочисленных проверок. Хорошо, если в конце очередной конструкции if … then можно просто поставить оператор exit. Обычно же для корректного выхода из ситуации нужно отменить целую последовательность действий, предшествующих неудачному. Все это сильно запутывает программу, размывая структуру главного алгоритма. При разработке приложений в Delphi программист имеет возможность использовать несколько механизмов, обеспечивающих обработку исключительных ситуаций. Это и специальные операторы языка Delphi, и классы, предназначенные для программирования реакции на ошибки. На этапе выполнения Delphi порождает исключения, когда какой-либо процесс идет неправильно. С точки зрения языка Delphi исключительная ситуация – это объект. Если код вашей подпрограммы написан соответствующим образом, он может распознать возникшую проблему и попытаться ее решить; в противном случае объект-исключение передается в код, который вызвал вашу подпрограмму и т.д. В конечном счете, если никто не обработал исключение, его обрабатывает Delphi, выводя на экран стандартное сообщение об ошибке и пытаясь продолжить выполнение программы. Весь механизм строится на следующих ключевых словах:

try – определяет начало защищенного блока кода;

except – определяет конец защищенного блока кода и вводит операторы обработки исключений в следующем виде: on <тип исключения> do <оператор>;

finally – указывает необязательный блок, который используется для освобождения ресурсов, распределенных в блоке try перед обработкой исключения; этот блок завершается ключевым словом end;

raise – оператор, используемый для порождения исключений. Большинство исключений, которые вы встретите при программировании на Delphi, будут порождаться системой, но вы также можете создать их в собственном коде, когда во время выполнения обнаружатся недопустимые или несогласованные данные. Кроме того, ключевое слово raise можно использовать внутри обработчика для повторного порождения исключения, т.е. для передачи его следующему обработчику. Если вы хотите, чтобы при правильной обработке исключений программа продолжала выполняться, отключите опцию отладки Break on Exception в окне Environment Options.

При возникновении исключительной ситуации директивы просматриваются последовательно, в порядке их описания. Каждый тип исключительной ситуации, описанный после ключевого слова on, обрабатывается именно этим блоком: только то, что предусмотрено в нем, и будет являться реакцией на данную ситуацию. Перечень предопределенных исключений Delphi представлен в табл. 9.1.

                                                                                           Таблица 9.1

Исключение Описание
1 2
Exception Базовый класс-предок всех обработчиков исключительных ситуаций
EAbort "Скрытое" исключение. Используется тогда, когда необходимо прервать тот или иной процесс с условием, что пользователь программы не должен видеть сообщения об ошибке. Для повышения удобства использования в модуле SysUtils предусмотрена процедура Abort, определенная как: procedure Abort; begin raise EAbort.CreateRes(SOperationAborted) at ReturnAddr; end;
EComponentError Вызывается в двух ситуациях: 1) при попытке регистрации компоненты за пределами процедуры Register; 2) когда имя компоненты не уникально или не допустимо
EConvertError Происходит в случае возникновения ошибки при выполнении функций StrToInt и StrToFloat, когда конвертация строки в соответствующий числовой тип невозможна
EInOutError Происходит при ошибках ввода/вывода при включенной директиве {$I+}

                                                                      Продолжение табл. 9.1

1 2
EIntError Предок исключений, случающихся при выполнении целочисленных операций
EDivByZero Вызывается в случае деления на ноль, как результат RunTime Error 200
EIntOverflow Вызывается при попытке выполнения операций, приводящих к переполнению целых переменных, как результат RunTime Error 215 при включенной директиве {$Q+}
ERangeError Вызывается при попытке обращения к элементам массива по индексу, выходящему за пределы массива, как результат RunTime Error 201 при включенной директиве {$R+}
EInvalidCast Происходит при попытке приведения переменных одного класса к другому классу, не совместимому с первым (например, приведение переменной типа TListBox к TMemo)
EInvalidGraphic Вызывается при попытке передачи в LoadFromFile файла, несовместимого графического формата
EInvalidGraphicOperation Вызывается при попытке выполнения операций, неприменимых для данного графического формата (например, Resize для TIcon)
EListError Вызывается при обращении к элементу наследника TList по индексу, выходящему за пределы допустимых значений (например, объект TStringList содержит только 10 строк, а происходит обращение к одиннадцатому)
EMathError Предок исключений, случающихся при выполнении операций с плавающей точкой
EOverflow Происходит как результат переполнения операций с плавающей точкой при слишком больших величинах. Соответствует RunTime Error 205
Underflow Происходит как результат переполнения операций с плавающей точкой при слишком малых величинах. Соответствует RunTime Error 206
EZeroDivide Вызывается в результате деления на ноль
EMenuError Вызывается в случае любых ошибок при работе с пунктами меню для компонент TMenu, TMenuItem, TPopupMenu и их наследников
EOutlineError Вызывается в случае любых ошибок при работе с TOutLine и любыми его наследниками
EOutOfMemory Соответствует RunTime Error 203.Происходит в случае вызовов New(), GetMem() или конструкторов классов при невозможности распределения памяти
EPrinter Вызывается при любых ошибках работы с принтером

                                                                      Продолжение табл. 9.1

1 2
EProcessorException Предок исключений, вызываемых в случае прерывания процессора- hardware breakpoint. Никогда не включается в DLL, может обрабатываться только в "цельном" приложении
EBreakpoint Вызывается в случае останова на точке прерывания при отладке в IDE Delphi. Среда Delphi обрабатывает это исключение самостоятельно
EFault Предок исключений, вызываемых в случае невозможности обработки процессором тех или иных операций
EInvalidOpCode Вызывается, когда процессор пытается выполнить недопустимые инструкции
ESingleStep Аналогично EBreakpoint, это исключение происходит при пошаговом выполнении приложения в IDE Delphi
EPropertyError Вызывается в случае ошибок в редакторах свойств, встраиваемых в IDE Delphi. Имеет большое значение для написания надежных property editors. Определен в модуле DsgnIntf.pas
EResNotFound Происходит в случае тех или иных проблем, имеющих место при попытке загрузки ресурсов форм – файлов .DFM в режиме дизайнера. Часто причиной таких исключений бывает нарушение соответствия между определением класса формы и ее описанием на уровне ресурса (например, вследствие изменения порядка следования полей-ссылок на компоненты, вставленные в форму в режиме дизайнера)
EStreamError Предок исключений, вызываемых при работе с потоками
EFCreateError Происходит в случае ошибок создания потока (например, при некорректном задании файла потока)
EFilerError Вызывается при попытке вторичной регистрации уже зарегистрированного класса (компоненты). Является, также, предком специализированных обработчиков исключений, возникающих при работе с классами компонент

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

При использовании компонента Edit для ввода чисел пользователь вместо цифры может набрать букву. Функции преобразования позволяют вернуть код ошибки, что поможет определить, действительно ли введено число. Выполнение такой проверки возможно тогда, когда изменится значение блока редактирования, когда компонент потеряет фокус или когда пользователь щелкнет по некоторой кнопке в диалоговой панели. Также возможно просматривать входной поток в блоке редактирования и останавливать любой нечисловой код.

 

Указания к выполнению работы

 

Допустим, имеется поле редактирования, в котором допускается ввод только числовых значений. Однако пользователь вместо цифры вполне может набрать и букву. Проверку корректности вводимого числа можно выполнить, когда изменится значение поля редактирования (событие OnChange), когда компонент потеряет фокус (событие OnExit). Проверка корректности может быть выполнена несколькими различными способами. Во-первых, можно использовать функцию val. Функция val имеет следующую сигнатуру:

 

procedure val(S; var V; var Code:integer);

 

Функция конвертирует строковое значение S в число V. Для её использования необходимо предварительно объявить переменную V, которая может быть как целочисленного типа, так и вещественного, а также переменную Code, в которой возвращается позиция ошибочного символа в S – или 0, если в S находится корректно заданное число. Таким образом, чтобы определить, находится ли в поле ввода корректное число, нужно воспользоваться функцией val и проверить, содержится ли в переменной Code нулевое значение. Если нет, то можно, например, вернуть фокус в поле (с помощью метода SetFocus поля редактирования) и вывести сообщение, к примеру:

 

MessageDlg(‘В поле введено нечисловое значение!‘,mtError,[mbOK],0);

 

Функция MessageDlg выводит сообщение в окошке с пиктограммой (в данном случае – с пиктограммой ошибки); простейшее же сообщение можно вывести с помощью процедуры ShowMessage, единственный параметр которой задаёт выводимый текст. Однако наиболее продвинутые возможности предоставляет функция MessageBox глобального объекта Application класса TApplication, который также позволяет получить доступ к ряду полезных возможностей созданного приложения в целом (в отличие от классов отдельных форм, например). При использовании функции MessageBox можно указать не только пиктограмму для выводимого сообщения, но и строчку, которая будет выведена в заголовке соответствующей формы. К примеру:

 

Application.MessageBox(‘В поле введено нечисловое значение!’,

‘Ошибочный ввод’, MB_ICONSTOP);

 

Во-вторых, можно обработать исключительную ситуацию, возникшую при попытке конвертирования строки в число. Обработка исключений – универсальный способ выявления и реакции на ошибочные ситуации в программе. Программный код, в котором возможна исключительная ситуация, помещается в блок tryexcept, например:

 

Try

StrToInt(Edit1.Text);

Except

on E:EConvertError do

ShowMessage(‘Класс ошибки: ’+E.ClassName+‘, сообщение: ‘+E.Message);

end;

 

В данном случае перед названием класса исключительной ситуации EConvertError указан идентификатор, представляющий объект-исключение. Он действует только в пределах блока обработки исключения и позволяет получить некоторые характеристики исключительной ситуации. Однако его использование необязательно, равно как и конструкции ondo (можно сразу обрабатывать исключение после слова except, не анализируя класс исключительной ситуации). Однако зачастую ошибочный ввод проще и удобнее предотвратить, просто не позволив пользователю ввести неверный символ. Для этого используется событие поля редактирования OnKeyPress, возникающее при нажатии клавиши клавиатуры. К примеру:

 

begin

if not (Key in [‘0’..‘9’,#8]) then

Begin

Key:=#0;

beep

end;

end;

 

Если очередной вводимый символ – не цифра, то его ввод подавляется и выводится звуковой сигнал. Наконец, вместо простого компонента Edit может быть использован компонент MaskEdit, который предоставляет возможность форматированного (маскированного) ввода. Маска описывается в свойстве EditMask, которое имеет в Object Inspector встроенный редактор с заготовками наиболее распространённых масок. Дополнительную информацию о значении символов масок и её формате можно получить в разделе справочной системы Delphi, сопоставленном свойству EditMask. Нарушение ограничений, накладываемых маской (к сожалению, она не гарантирует ввода правильного значения: например, для числового формата возможен ввод пустых позиций внутри числа), приводит генерации исключения EDBEditError при попытке выхода из поля. При этом выдаётся стандартное английское сообщение, что едва ли приемлемо. Возможностей «русифицировать» его немного, поскольку размещать блок try … except некуда. Единственный правильный способ – это перехват всех исключений и распознавание нужного. Для этого существуют два альтернативных способа. Во-первых, можно задать обработчик OnException объекта Application. При этом стандартный обработчик замещается вашим собственным. К примеру:

 

procedure TForm1.MyException(Sender:TObject; E:Exception);

Begin

if (E.ClassName='EDBEditError') AND (...) then

...

end;

procedure TForm1.FormCreate(Sender:TObject);

Begin

Application.OnException:=MyException;

end;

 

Во-вторых, более простым способом является применение невизуального компонента ApplicationEvents и его событие OnException, которое используется аналогично.

 

Контрольные вопросы и задания

 

1. Что такое "исключительная ситуация"?

2. На каких ключевых словах строится механизм обработки исключений?

3. Как строится программная конструкция на основе этих ключевых слов?

4. В обработчики каких событий вводятся эти конструкции?

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

 

 


Дата добавления: 2018-05-13; просмотров: 709; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!