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

Программирование с использованием механизма
обработки исключительных ситуаций

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

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

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

До появления C++ Builder в Borland C++ выделяли два вида управления исключительными ситуациями:

управление исключительными ситуациями, характерное для языка C++; структурное, или структурированное (structured exception) управление, характерное для языка С.

В C++ Builder добавились механизмы обработки исключительных ситуаций, обусловленных применением библиотеки визуальных компонентов (VCL Visual Component Library).

Для обработки исключительных ситуаций, связанных с применением VCL и управлением исключительными ситуациями C++, следует использовать в общем случае конструкцию вида:

try

{<операторы>}

catch (<описание исключительной ситуации E1>)

{<операторы обработчика исключительной ситуации E1>}

 catch (<описание исключительной ситуации E2>)

{<операторы обработчика исключительной ситуации E2>}

catch (<описание исключительной ситуации En>)

{<операторы обработчика исключительной ситуации En>}

catch (...)

{<операторы       для обработки не предусмотренной выше исключительной

ситуации>}

Для каждой i-й исключительной ситуации, связанной с применением VCL, описание исключительной ситуации Ei в общем случае должно иметь вид:

const <имя класса исключительной ситуации Ei> &Ei

Наличие ключевого слова const и переменной Ei необязательно.

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

Таблица 10.1.

Имя класса исключительной ситуации

Причина возникновения исключительной ситуации

EAbort

Намеренное прерывание выполнения программы

EAccessViolation

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

EConvertError

Ошибка преобразования данных одного типа в данные другого типа

EDivByZero

Попытка целочисленного деления на ноль

EIntOverflow

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

EInOutError

Ошибки при файловом вводе/выводе

EZeroDivide

Деление на ноль числа с плавающей точкой

 

 

При обработке исключительных ситуаций C++ описание i-й исключительной ситуации следует в общем случае представлять в виде:

<имя типа данных, соответствующее исключительной ситуации Ei> Ei

Указание переменной Ei необязательно. В качестве имени типа данных, соответствующего исключительной ситуации Ei, может выступать int, const char*, void*, ссылка на класс, определённый пользователем, и.т.д.

Реализация механизмов обработки исключительных ситуаций, характерных для С (которые, разумеется, широко применяются в текстах программ на C++), осуществляется с помощью одной из следующих конструкций:

try                                                    try

{операторы}                                    {операторы}

                                                        

__eхсерt(<фильтр>)                        __ finally

{обработка исключительной          {операторы завершения

ситуации }                                       работы блока try}

С помощью конструкции try ... _____ except реализуется так называемое

кадрированное управление, а с помощью try.__ finally завершающее

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

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

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

except. Если исключительная ситуация не возникает, то выполняются только

операторы, расположенные внутри фигурных скобок, стоящих после слова try. В

этом случае операторы, расположенные после catch и__ except не выполняются.

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

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

Определённые отличия имеются в работе конструкции try._ finally.

Если исключительная ситуация не возникает, то сначала выполняются

операторы тела защищённого кода, а затем - операторы внутри блока_ finally

(так называемый завершающий блок). При возникновении исключительной

ситуации выполнение сразу передается в блок ______ finally, который обычно

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

В конструкции try.______ except фильтр, или точнее фильтрующее

выражение может принимать одно из трёх возможных значений: 1)EXCEPTION_EXECUTE_HANDLER (такое значение фильтра указывает, что управление должно быть передано соответствующему обработчику исключительной ситуации);

2) EXCEPTION CONTINUE SEARCH ( в этом случае не будет происходить выполнение того обработчика, который непосредственно связан с данным  except, а будет осуществлён поиск иного обработчика);

3) EXCEPTION CONTINUE EXECUTION (это значение фильтра позволяет вновь вернуть управление выполнением программы в место, где была заявлена исключительная ситуация).

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

Следует отметить, что интегрированная среда разработки C++ Builder сама отслеживает и обрабатывает возникающие исключительные ситуации. Для отладки программы, содержащей собственную обработку исключительных ситуаций, надо отключить опции Stop on Delphi Exceptions и Stop on C++ Exceptions, находящиеся в Tools - Debbuger Options ... , закладка Language Exceptions.

Возникновение исключительной ситуации может быть инициировано преднамеренно. Для этого можно использовать ключевое слово throw или функцию RaiseException(). Ключевое слово throw позволяет “выбросить” (если применять терминологию языка C++) исключение. За словом throw может следовать операнд (если это требуется). Он определяет тип генерируемой исключительной ситуации, а следовательно, и то, какой обработчик будет обрабатывать исключительную ситуацию. Допустимо использовать как встроенные типы языка C++, так и определённые пользователем. Ключевое слово throw используется и для генерации исключительных ситуаций, связанных с применением VCL. Для того чтобы “заявить” (по терминологии языка C++) исключительную ситуацию, можно использовать функцию

RaiseException (< Код исключительной ситуации >,

                 <тип исключительной ситуации>,

                 <количество элементов в массиве аргументов>,

                 <адрес массива аргументов>)

Первые три параметра имеют тип DWORD, четвёртый — const DWORD*/

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

10.2.Системы счисления

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

 

где at - цифры, p - основание системы счисления. Количество цифр равно р. Для

записи цифр в общем случае может быть использован любой набор P символов. Обычно при p < 10 используются символы 0 - 9, для p > 10 добавляются буквы латинского алфавита A, B, C, D, E, F, которые в десятичной системе представляют числами 10, 11, 12, 13, 14, 15. Например,

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

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

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

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

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

10.3.Порядок выполнения индивидуального задания

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

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

Панель диалога будет иметь вид (рис. 10.1).

 

Текст программы:

#include <vcl.h>

#pragma hdrstop

#include "Unit1.h"

//--------------------------------------------------------------------------  

 #pragma package(smart_init)

#pragma resource "*.dfm"

TForml *Form1;

long value;

//----------------------------------------------------------------------------

___fastcall TForm1::TForm1(TComponent* Owner)

: TForm(Owner)

{

}

//-----------------------------------------------------------------------------        

void___fastcall TForm1::Edit1Change(TObject *Sender)

{

char *endptr;

AnsiString C="ABCDEFGabcdefg0123456789";

if (Edit1->Text!="")

{try

{Edit1->Color=clYellow;

if (Edit2->Text!="") Edit3->Color=clFuchsia;

if((Edit1->Text[1]=='-')&&(Edit1->Text.Length()==1)) return;

 if (C.AnsiPos(Edit1->Text[Edit1->Text.Length()])==0)

throw EConvertError("");

value=strtol(Edit1->Text.c_str(),&endptr,17);

 if ((Edit1->Text.Length()>11)&&(value==MaxInt))

 throw EIntOverflow("");

} catch (EConvertError &)

{if (Edit1->Text!='-')

ShowMessage("Возможны лишь цифры от 0 до 9 и буквы

 от A до G,или "+ AnsiString(" от a до g!"));

 Edit1->Text=Edit1->Text.SetLength(Edit1->Text.Length()-1);

Edit1->SelStart=Edit1->Text.Length();

}

catch (EIntOverflow &)

{ShowMessage("Слишком большое число!");

Edit1->Text=Edit1->Text.SetLength(Edit1->Text.Length()-1);

Edit1->SelStart=Edit1->Text.Length();

}

catch (...)

{ShowMessage("Возникла неизвестная исключительная ситуация!");}

}

}

//------------------------------------------------------------------------------

void___fastcall TForm1::Edit2Change(TObject *Sender)

{char *endptr;

int j=3;

AnsiString C,CComp="ABCDEFGabcdefg0123456789";

if (Edit2->Text!="")

{try

{Edit2->Color=clYellow;

if (Edit1->Text!="") Edit3->Color=clFuchsia;

if((Edit2->Text[1]=='-')&&(Edit2->Text.Length()==1)) return;

C=Edit2->Text[Edit2->Text.Length()];

try

{j=j/CComp.AnsiPos(C);}

___except(EXCEPTION_EXECUTE_HANDLER)

{Application->MessageBox("Вы ввели недопустимый символ!",

"Ошибка",MB_OK);

throw EAssertionFailed("");}

value=strtol(Edit2->Text.c_str(),&endptr,17);

if((Edit2->Text.Length()>11)&&(value==MaxInt))

throw EIntOverflow("");

}

catch (EAssertionFailed &)

{if (Edit2->Text!='-')

ShowMessage("Возможны лишь цифры от 0 до 9 и буквы от A до в,или "+

AnsiString(" от а до g!"));

Edit2->Text=Edit2->Text.Delete(Edit2->Text.Length(),1);

Edit2->SelStart=Edit2->Text.Length();

}

catch (EIntOverflow &)

{ShowMessage("Слишком большое число!");

 Edit2->Text=Edit2->Text.Delete(Edit2->Text.Length(),1);

Edit2->SelStart=Edit2->Text.Length();} catch (...)

{ShowMessage("Возникла неизвестная исключительная ситуация!");}

}

}

//---------------------------------------------------------------------

void___fastcall TForm1::Button1Click(TObject *Sender)

{

long x,y;

char s[11],s1[11],*endptr; try { try

{x=strtol(Edit1->Text.c_str(),&endptr,17);

y=strtol(Edit2->Text.c_str(),&endptr,17);

switch (RadioGroup1->ItemIndex)

{case 0:x=x+y;break;

case 1:x=x-y;break;

case 2:x=x*y;break;

case 3:x=x/y;break;

case 4:x=x%y; break;

}

if (x>=0) itoa(x,s,17);

else{itoa(-x,s,17);strcpy(s,strcat(strcpy(s1,"-"),s));}

if (stricmp(s,Edit3->Text.c_str())!=0) Abort();

else Message("Вы полностью правы!",mtInformation,

            TMsgDlgButtons()<<mbOK,0);}

catch (EIntOverflow &)

{MessageDlg("Переполнение при выполнении операции !",mtError,          TMsgDlgButtons()<<mbOK,0);}

catch (EDivByZero &)

{MessageDlg(" Делить на ноль нельзя !",mtError,     TMsgDlgButtons()<<mbOK,0);} catch(EConvertError &)

{MessageDlg("Ошибка исходных данных!",

               mtError, TMsgDlgButtons()<<mbOK,0);}

catch(EAbort &){MessageDlg " Вы неправильно вычислили!",

mtWammg, TMsgDlgButtons()<<mbOK,0);

Edit3->Text=AnsiString(s);}

catch(...)

{MessageDlg("Неизвестная исключительная ситуация!", mtError,TMsgDlgButtons()<<mbOK,0);

}

}

__finally

{Edit1->Color=clWindow;

Edit2->Color=clWindow;

Edit3->Color=clWindow;}

}

//--------------------------------------------------------------------

void___fastcall TForm1::RadioGroup1Click(TObject *Sender)

{

if (Edit1->Text!="") Edit1->Color=clYellow;

else Edit1->Color=clWindow;
if (Edit2->Text!="") Edit2->Color=clYellow;
else Edit2->Color=clWindow;

if ((Edit1->Text!="")&&(Edit2->Text!="")) Edit3->Color=clFuchsia;

else Edit3->Color=clWindow;

}

//---------------------------------------------------------------------

 

Индивидуальные задания

Создать приложение Windows, использующее механизм обработки исключительных ситуаций, позволяющее выполнять перевод вещественного числа из одной системы счисления в другую. Для обозначения использовать цифры 0 ... 9 и буквы латинского алфавита (прописные и строчные).

1.      Перевод числа из двоичной системы счисления в троичную.

2.       Перевод числа из троичной системы счисления в четырнадцатеричную

3.       Перевод числа из четверичной системы счисления в пятеричную.

4.       Перевод числа из восьмеричной системы счисления в шестеричную.

5.       Перевод числа из двоичной системы счисления в семеричную.

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

7.       Перевод числа из одиннадцатеричной      системы счисления в девятеричную.

8.       Перевод числа из семеричной системы счисления в одиннадцатеричную.

9.    Перевод числа из восемнадцатеричной системы счисления в двенадцатеричную.

10.      Перевод   числа     из     двадцатеричной      системы      счисления     в тринадцатеричную.

11.      Перевод числа из девятеричной системы счисления в четверичную.

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

13.       Перевод числа из троичной системы счисления в шестнадцатеричную.

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

15.        Перевод числа из двоичной системы счисления в девятнадцатеричную.