Видимость одной из RadioGroup

Лабораторная работа № 14

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

 

Цели работы:

1) Закрепление теоретических сведений по преобразованию типов данных при вычислениях

2) Закрепление теоретических сведений по работе со строками

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

Теоретические сведения:

Операторы try..except и try..fmally

Исключительная ситуация - это нештатное событие, могущее повлиять на дальнейшее выполнение программы. Современный компилятор дописывает код, который перехватывает любое такое событие, предотвращает дальнейшие нежелательные последствия, сохраняет необходимые данные о состоянии программы, и выдает разработчику. С точки зрения Object Pascal исключительная ситуация — это объект. Для работы с таким особенным объектом существуют специальные конструкции языка —блоки try...except и try..finally.

Для реакции на конкретный тип ситуации применяется блок try..except. Синтаксис его следующий:

try <0ператор> <0ператор>

except

on Exceptioni do < Оператор >;

on Exception2 do < Оператор >;

else { }

<0ператор> {обработчик прочих ИС} end;

Выполнение блока начинается с секции try. При отсутствии исключительных ситуаций только она и выполняется. Секция except получает управление в случае возникновения ИС. Обработчик ИС состоит из набора директив on... do, определяющих реакцию приложения на определенную ситуацию. Каждая директива связывает ситуацию (on...), заданную своим именем, с группой операторов (do...).

try

U := 220.0;

R := 0;

I := U / R;

except

on EZeroDivide do MessageBox(Деление на ноль!');

end;

В этом примере замена if.. .then на try.. .except внешне не дала очевидной экономии кода. Однако если при решении, допустим, вычислительной задачи проверять на возможное деление на ноль приходится не один, а множество раз, то выигрыш от нового подхода неоспорим — достаточно одного блока на все вычисления.

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

Если возникла ситуация, не определенная ни в одной из директив, выполняются те операторы, которые стоят после else. Если и их нет, то ИС считается не обработанной и будет передана на следующий уровень обработки. Этим следующим уровнем может быть другой оператор try. .except, который содержит в себе данный блок. На самом верхнем уровне вызывается обработчик ИС по умолчанию, предусмотренный в стандартном модуле sysutils.pas. После обработки происходит выход из защищенного блока, и управление обратно в секцию try не передается. Разумеется, если ИС произошла вне блока try. .except, это не обязательно приведет к аварийному завершению всего приложения. Обработчики по умолчанию сделаны так, что в этом случае заканчивается лишь выполнение метода, внутри которого возникла ИС. Стандартная обработка подразумевает вывод на экран панели текстового сообщения (из свойства Exception. Message) с указанием типа ошибки. Можно получить и развернутую информацию с именем модуля и адреса, где она имела место (рис. 6.1).

Рисунок 6.1-Типовое окно сообщения об ошибке

Для этого нужно вызвать функцию ExceptionErrorMessage, имеющуюся в модуле sysutils. pas. Подробнее о ней рассказано в разделе "Работа со свойствами исключительных ситуаций".

Если предусмотренной обработки ИС недостаточно, то можно продолжить ее дальше программно, при помощи оператора raise:

s1:= TStringList.Create;

try

s1.LoadFromFile(AFileName);

except

s1.Free;

raise;

end;

Здесь в случае возникновения исключительной ситуации созданный список строк должен быть уничтожен. Сама же обработка предоставляется "вышестоящим инстанциям".

Параллельно с блоком try. .except в языке существует и try. .finally. Он соответствует случаю, когда необходимо возвратить выделенные программе ресурсы даже в случае аварийной ситуации. Синтаксис блока try.. .finally таков:

try

<0ператор> <0ператор>

finally <0ператор>

end;

Следующие за try операторы выполняются в обычном порядке. Если за это время не возникло никаких ИС, далее выполняются те операторы, которые стоят после finally. В случае, если между try и finally произошла ИС, управление немедленно передается на оператор(ы) после finally, которые называются кодом очистки. Допустим, вы поместили после try операторы, которые должны выделить вам ресурсы системы (дескрипторы блоков памяти, файлов, контекстов устройств и т. п.). Тогда операторы, освобождающие их, следует поместить после finally, и ресурсы будут освобождены в любом случае. Блок try. .finally, как можно догадаться, еще называется блоком защиты ресурсов.

Важно обратить внимание на такой факт: данная конструкция ничего не делает с самим объектом— исключительной ситуацией. Задача try.. finally -только прореагировать на факт нештатного поведения программы и проделать определенные действия. Сама же ИС продолжает "путешествие" и вопрос ее обработки остается на повестке дня.

Блоки защиты ресурсов и обработчики ИС, как и другие блоки, могут быть вложенными. В этом простейшем примере каждый вид ресурсов системы защищается в отдельном блоке:

try AllocatelstResource;

try Allocate2ndResource;

SolveProblem;

finally FreeZndResource;

end;

finally FreelstResource;

end;

Можно также вкладывать обработчики друг в друга, предусмотрев в каждом специфическую реакцию на ту или иную ошибку:

var i,j,k : Integer;

begin

i := Round(Random);

j := 1 -i;

try

k := 1 div i;

try

k := 1 div j;

except

On EDivByZero do ShowMessage('Вариант 1') ;

end;

except

On EDivByZero do

ShowMessage('Вариант 2');

end;

end;

Но все же самый распространенный случай — это сочетание блоков двух типов. В один из них помещается общее (освобождение ресурсов в finally), в другой — особенное (конкретная реакция внутри except).

Исключительные ситуации как объекты

Чем же различаются между собой исключительные ситуации? Как отличить Exceptioni от Exception2? Поскольку это объекты, они отличаются классом (объектным типом). Объектный тип Exception описан в модуле sysutils. pas. Он является предком для всех других объектов— исключительных ситуаций.

Exception = class(TObject) public

constructor Create(const Msg: string);

constructor CreatePtnt(const Msg: string; const Args: array of const);

constructor CreateRes(Ident: Word);

constructor CreateResFmt(Ident: Word; const Args: array of const);

constructor CreateHelp(const Msg: string; AHelpContext: Longint);

constructor CreateFtntHelp (const Msg: string; const Args: array of const;

AHelpContext! Longint);

constructor CreateResHelp(Ident: Word; AHelpContext: Longint);

constructor CreateResFmtHelp(Ident: Word; const Args: array of const;

AHelpContext: Longint) ;

property HelpContext: Longint;

property Message: string;

end;

ExceptClass = class of Exception;

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

Конструкторы, в названии которых встречается подстрока fmt, могут вставлять в формируемый текст сообщения об ошибке значения параметров, как это делает стандартная функция Format:

If MemSize>Limit then

raise EOutOfMemory.CreateRnt('Cannot allocate more than %d bytes',[Limit]);

Если в названии присутствует подстрока Res, это означает, что текст сообщения будет загружаться из ресурсов приложения. Это особенно полезно при создании локализованных версий программных продуктов, когда нужно сменить язык всех сообщений, ничего не перекомпилируя.

И наконец, если в названии фигурирует подстрока Help, то такой конструктор инициализирует свойство HelpContext создаваемого объекта. Естественно, система помощи должна быть создана и в ней должна иметься статья, связанная с этим контекстом. Теперь пользователь может затребовать помощь для данной ситуации, скажем, нажав клавишу <F1> в момент показа сообщения об ИС.

Тип Exception порождает многочисленные дочерние типы, соответствующие часто встречающимся случаям ошибок ввода/вывода, распределения памяти и т. п. Заметим, что Exception и его потомки представляют собой исключение из правила, предписывающего все объектные типы именовать с буквы т. Потомки Exception начинаются С Е, Например, EZeroDivide.

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

 

 

Таблица 6.1. ИС работы с памятью (порождены отЕНеарЕхсерNоп)

Тип Условие возникновения
EOutOfMemory Недостаточно места в памяти
EOutOfRe sources Нехватка системных ресурсов
EinvalidPointer Недопустимый указатель (обычно nil)

 

Таблица 6.2. ИС целочисленной математики (порождены от EintError)

Тип Условие возникновения
EdivByZero Попытка деления на ноль (целое число)
ErangeError Число или выражение выходит за допустимый диапазон
EintOverflow Целочисленное переполнение

 

Таблица 6.3. ИС математики с плавающей точкой (порождены от EMa thError)

Тип Условие возникновения
EInvalidOp Неверная операция
EZeroDivide Попытка деления на ноль
EOverflow Переполнение с плавающей точкой
EUnderflow Исчезновение порядка
EInvalidArgument Неверный аргумент математических функций

 

Самое важное в объекте Exception — это класс, к которому он принадлежит. Именно факт принадлежности возникшей ИС к тому или иному классу говорит о том, что случилось. Если же нужно детализировать проблему, можно присвоить значение свойству Message. Если и этого мало, можно добавить в объект новые поля. Так, в ИС EinOutError (ошибка ввода/вывода) есть поле ErrorCode, значение которого соответствует произошедшей ошибке — запрету записи, отсутствию или повреждению файла, и т. д.

Методические указания:

Обработчик ошибочных ситуаций

try

if radiogroup2.itemindex=0 then

case radiogroup1.ItemIndex of

0: z:=cos(x)/sin(x);

1: z:=sqr(x)*x;

2: z:=ln(x);

3: z:=sqrt(x);

end else

case radiogroup3.itemindex of

0: z:=ln(y)/ln(x);

1: z:=x+y;

end;

edit3.text:=floattostrf(z,fffixed,6,3);

if checkbox1.checked then

label1.caption:=s+' = '+edit3.text;

except

on EZeroDivide do

messagedlg('Делить на ноль нельзя!',mterror,[mbok],0);

on EInvalidOp do

messagedlg('Неверный аргумент функции!',mterror,[mbok],0);

Видимость одной из RadioGroup

 

procedure TForm1.RadioGroup2Click(Sender: TObject);

begin

case radiogroup2.ItemIndex of

0: begin

edit2.Hide;

radiogroup3.Hide;

radiogroup1.show;

end;

1: begin

radiogroup1.Hide;

edit2.Show;

radiogroup3.show;

end;

end;

end;

 

Отображение формулы в зависимости от включенного переключателя CheckBox

 

procedure TForm1.CheckBox1Click(Sender: TObject);

begin

if checkbox1.Checked then

begin

Label1.Show;

end

else

begin

label1.Hide;

end;

 

end;

 

Процедура вычисления с учетом исключительных ситуаций

 

procedure TForm1.BitBtn1Click(Sender: TObject);

begin

try

case radiogroup2.ItemIndex of

0: begin

x:=strtofloat(edit1.Text);

case radiogroup1.ItemIndex of

0: begin

z:=pi/x;

 

label1.Caption:='pi/'+edit1.Text+'='+floattostrf(z,fffixed,4,3);

end;

1: begin

z:=(Exp(4*x)+Exp(4*(-x)))/2;

label1.Caption:='Ch4('+edit1.Text+')='+floattostrf(z,fffixed,4,3);

end;

2: begin

z:=Exp(7*Ln(x));

label1.Caption:=edit1.Text+'^7='+floattostrf(z,fffixed,4,3);

end;

3: begin

z:=cos(x);

label1.Caption:='cos('+edit1.Text+')='+floattostrf(z,fffixed,4,3);

end;

end;

end;

1: begin

x:=strtofloat(edit1.Text);

y:=strtofloat(edit2.Text);

case radiogroup3.ItemIndex of

0: begin

z:=5*x*y-4;

label1.Caption:='5*'+edit1.Text+'*'+edit2.text+'-4'+'='+floattostrf(z,fffixed,4,3);

end;

1: begin

z:=exp(3*x*y);

label1.Caption:='e^(3*'+edit1.Text+'*'+edit2.text+')='+floattostrf(z,fffixed,4,3);

end;

end;

end;

end;

except

on EZeroDivide do

messagedlg('Делить на ноль нельзя!',mterror,[mbok],0);

on EInvalidOp do

messagedlg('Неверный аргумент функции!',mterror,[mbok],0);

end;

edit3.Text:=floattostrf(z,fffixed,4,3);

end;

procedure TForm1.FormCreate(Sender: TObject);

begin

radiogroup2.ItemIndex:=0;

application.HintColor:=clYellow;

checkbox1.Checked:=true;

radiogroup3.ItemIndex:=0;

end;

Практическая часть

Задание:

1. Создать новый проект. Изменить заголовок формы "Лабораторная работа 14. Фамилия Имя. Группа".

2. Установить на форме необходимое количество объектов, позволяющих вводить значения двух чисел и вычислять либо функцию одного числа, либо арифметическую операцию с двумя числами в зависимости от варианта задания (Таблица 14.1). Для отображения значения использовать компонент TEdit, для поясняющего текста – Tlabel (Рисунок 14.1).

3. Предусмотреть возникновение исключительных ситуаций:

- деление на ноль;

- ноль деленный на ноль;

- отсутствие значения в поле ввода;

- ввод не числового значения, а буквы.

4. Предусмотреть выключатель видимости формулы вычисления и распознавание ошибочных ситуаций (Рисунок 14.2)

5. Вещественные значения выводить в фиксированном формате с тремя знаками после запятой.

Таблица 14.1 Задание на вычислительные операции

Вариант Операции с одним аргументом Операции с двумя аргументами
1 подгруппа ex, , ln(x) , tg(x) x/y, logxy
2 подгруппа 1/x, ctg x, , ln(x) xy, 2π/y

Рисунок 14.1

Рисунок 14.2

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

7. Создать проект, используя для каждого значения элементы TEdit (для отображения значения) и TLabel (для поясняющего текста), который позволял бы менять указанные значения так, что при каждом изменении пересчитывались бы другие значения по соответствующей формуле.

8. Для оформления приложения предусмотреть вызываемую форму СПРАВКА. Для вызова формы справки, перехода от вычислений одного операнда и двух, выхода из приложения предусмотреть компонент MainMenu, содержащий пункты: ВЫЧИСЛЕНИЕ/Один операнд (вложенность структур)/Два операнда (вложенность структур) с возможностью автоматической загрузки первоначальных значений (пример 1…пример 4), СПРАВКА, ВЫХОД. Форма СПРАВКА должна содержать формулы вычисляемых функций и примеры вычислений.

 

Отчет по работе должен содержать:

1) Формулировку задания согласно варианту.

2) Порядок выполнения работы.

3) Программный код всех процедур.

4) Выводы по работе.