Стандартные исключения, try, throw

Задания раздела 5.6.3
5.23. Напишите программу, которая читает два целых числа со стандартного устройства ввода и выводит результат деления первого числа на второе.
5.24. Перепишите предыдущую программу так, чтобы она передавала исключение, если второе число - нуль. Проверьте свою программу с нулевым вводом, чтобы увидеть происходящее при отсутствии обработчика исключения.
5.25. Перепишите предыдущую программу так, чтобы использовать для обработки исключения блок try. Раздел catch должен отобразить сообщение и попросить пользователя ввести новое число и повторить код в блоке try.

5.6.3

Перед тем как приступить к заданиям будет много текста. Потому что это все для меня абсолютно новая и неизведанная тема.
Исключение (exception) - это аномалии времени выполнения, которые нарушают нормальное функционирование программы.
Если есть часть программы, которая может передать исключение, должна быть часть, которая может это исключение обработать. Исключения обеспечивают взаимодействие частей программы, обнаруживающих проблему и решающих её.
Оператор throw передает исключение. Если код обнаружил проблему и не может быть исполнен, используется оператор throw.
Блок try используется для обработки исключения. Блок начинается с ключевого слова try и завершается одной или несколькими директивами catch. Исключения из блока try обрабатываются в одном из разделов catch.
Набор библиотечных классов исключений (exeption class) используется  для передачи информации о произошедшем между операторами throw и соответствующими разделами catch.

Оператор throw.
Обнаруживающая  часть программы использует оператор throw для передачи исключения.
Тип runtime_error является одним из типов исключения, определенных в заголовке stdexcept стандартной библиотеки. Объект класса runtime_error следует инициализировать объектом класса string или символьной строкой в стиле C.
Лучше всего иллюстрирует эти крошки информации следующий пример:
#include <iostream>
#include <string>
#include <stdexcept>
int main()
{
double i, j;
std::cout << "Enter two numbers:" << std::endl;
std::cin >> i >> j;
if (j==0)
throw std::runtime_error ("division by zero");
std::cout << i<<"/"<<j<<"=" << i/j;
return(0);
}

Блок try.
Синтаксис:
try {операторы программы}
catch (объявление исключения) {операторы обработчика}
catch (объявления исключения) {операторы обработчика}
Когда объявление исключения в блоке catch совпадает с исключением, выполняется связанный с ним блок. По завершении выполнения кода обработчика управление переходит к оператору, следующему непосредственно после него.
Операторы программы в блоке try являются обычными программными операторами, реализующими её логику. Блоки try могут содержать любые операторы  языка C++, включая объявления. Объявленные в блоке try переменные недоступны вне блока. В частности, они не доступны в блоках catch.
Как водится, пример в студию:
#include <iostream>
#include <string>
#include <stdexcept>
int main()
{
double i, j; std::string t;
std::cout << "Enter two numbers:" << std::endl;
std::cin >> i >> j;
try {
if (j==0)
throw std::runtime_error ("division by zero");
std::cout << i<<"/"<<j<<"=" << i/j;
}
catch (std::runtime_error err)
{std::cout << err.what()<< std::endl;}
return(0);
}
Данная программа даёт некоторое представление о том, как работает обработчик.
Операторы в блоке после ключевого слова catch определяют действия, выполняемые в случае, если код в блоке try  передаст исключение runtime_error. В сообщении об ошибке используется текст, возвращенный функцией  err.what(). Классом объекта исключения err является runtime_error, функция what() является членом класса runtime_error. В каждом из библиотечных классов исключений определена функция-член what(), которая не получает никаких аргументов и возвращает символьную строку в стиле C (const char*). В случае класса runtime_error эта строка является копией строки, использованной при инициализации объекта класса runtime_error.
Предыдущую программу можно сделать в цикле, чтобы вводить числа до ввода отказа в виде символа n.
#include <iostream>
#include <string>
#include <stdexcept>
int main()
{
double i, j;
std::cout << "Enter two numbers:" << std::endl;
while (std::cin >> i >> j) {
try {
if (j==0)
throw std::runtime_error ("division by zero");
std::cout << i<<"/"<<j<<"=" << i/j<<std::endl;
}
catch (std::runtime_error err)
{std::cout << err.what()<< std::endl;
std::cout << "\nWanna do more calculations? (y/n) "<<std::endl;
char c;
std::cin >> c;
if (!std::cin || c=='n') break;
else std::cout << "Enter two numbers:" << std::endl;
}
}
return(0);
}
Важно помнить, что исключения прерывают нормальный поток выполнения программы. В месте, где происходит исключение, некоторые из действий, ожидаемых вызывающей стороной, могут быть выполнены, а другие нет. Как правило, пропуск части программы может означать, что объект останется в недопустимом или неполном состоянии, либо что ресурс не будет освобожден.

Стандартные исключения.
В библиотеке C++ определен набор классов, объекты которых можно использовать для передачи сообщений о проблемах в функциях. Библиотечные классы исключений определены в четырех следующих заголовках.
В заголовке exeption определен общий класс исключения exeption. Он сообщает только о том, что исключение произошло, но не предоставляет никакой дополнительной информации.
В заголовке stdexcept определено несколько универсальных классов исключения.
В заголовке new определен класс исключения bad_alloc.
В заголовке type_info определен класс исключения bad_cast.
В классах exception, bad_alloc, bad_cast определен только стандартный конструктор, поэтому невозможно инициализировать объект этих типов.
Поведение исключений других типов прямо противоположно: их можно инициализировать объектом класса string или строкой в стиле C, однако значением по-умолчанию их инициализировать нельзя. При создании объекта исключения любого из этих типов необходимо предоставить инициализатор. Этот инициализатор используется для представления дополнительной информации о произошедшей ошибке.

Стандартные классы исключений, определенные в заголовке stdexcept:
exeption // наиболее общий вид проблемы
runtime_error // проблема, которая может быть обнаружена только во время выполнения
range_error // Ошибка времени выполнения: полученный результат превосходит допустимый диапазон значения
overflow_error // Ошибка времени выполнения: переполнение регистра при вычислении
underflow_error // Ошибка времени времени выполнения: недополнение регистра при вычислении
logic_error // Ошибка в логике программы
domain_error // Логическая ошибка: аргумент, для которого не существует результата
invalid_argument // Логическая ошибка: неподходящий аргумент
length_error // Логическая ошибка: попытка создать объект большего размера, чем максимально допустимый для данного типа
out_of_range // Логическая ошибка: используемое значение вне допустимого диапазона

В классах исключений определена только одна функция what(). Она не получает никаких аргументов и возвращает константный указатель на тип char. Это указатель на символьную строку в стиле C, содержащую текст описания переданного исключения.

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

#include <iostream>
int main()
{
double i, j;
std::cout << "Enter two numbers:" << std::endl;
while (std::cin >> i >> j) {
std::cout << i<<"/"<<j<<"=" << i/j<<std::endl;
std::cout << "\nWanna do more calculations? (y/n) "<<std::endl;
char c;
std::cin >> c;
if (!std::cin || c=='n') break;
else std::cout << "Enter two numbers:" << std::endl;
}
return(0);
}

5.24. Перепишите предыдущую программу так, чтобы она передавала исключение, если второе число - нуль. Проверьте свою программу с нулевым вводом, чтобы увидеть происходящее при отсутствии обработчика исключения.

#include <iostream>
#include <string>
#include <stdexcept>
int main()
{
double i, j;
std::cout << "Enter two numbers:" << std::endl;
std::cin >> i >> j;
if (j==0)
throw std::runtime_error ("division by zero");
std::cout << i<<"/"<<j<<"=" << i/j;
return(0);
}

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

#include <iostream>
#include <string>
#include <stdexcept>
int main()
{
double i, j;
std::cout << "Enter two numbers:" << std::endl;
while (std::cin >> i >> j) {
try {
if (j==0)
throw std::runtime_error ("division by zero");
std::cout << i<<"/"<<j<<"=" << i/j<<std::endl;
}
catch (std::runtime_error err) {
std::cout << err.what()<< std::endl;

std::cout << "\nWanna do more calculations? (y/n) "<<std::endl;
char c;
std::cin >> c;
if (!std::cin || c=='n') break;
else std::cout << "Enter two numbers:" << std::endl;
}
}
return(0);
}

Добавить комментарий