Форум программистов, компьютерный форум, киберфорум
Наши страницы
acmades
Войти
Регистрация
Восстановить пароль
Оценить эту запись

С++ «Неделя четвертая - Исключения - Исключения в классе Rational» #22

Запись от acmades размещена 24.08.2017 в 14:18

Продолжаю курс: «Основы разработки на C++: белый пояс»
Простое задание:
Ссылка на предыдущее задание
Вспомним класс Rational, который мы реализовали в задачах, посвящённых перегрузке операторов. Там специально говорилось, что в тестах объекты класса Rational никогда не создаются с нулевым знаменателем и никогда не выполняется деление на ноль. Настало время избавиться от этого ограничения и научиться обрабатывать нулевой знаменатель и деление на ноль. В этой задаче вам предстоит это сделать.

Поменяйте реализацию конструктора класса Rational так, чтобы он выбрасывал исключение invalid_argument, если знаменатель равен нулю. Кроме того, переделайте реализацию оператора деления для класса Rational так, чтобы он выбрасывал исключение domain_error, если делитель равен нулю.

Напомним, что вам надо реализовать интерфейс
C++
1
2
3
4
5
6
7
8
class Rational {
public:
  Rational();
  Rational(int numerator, int denominator);
 
  int Numerator() const;
  int Denominator() const;
};
и оператор деления для класса Rational
C++
1
Rational operator / (const Rational& lhs, const Rational& rhs);
Моё решение:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
/*Неделя четвертая - Исключения - Исключения в классе Rational*/
#include <iostream>
#include <exception>
#include <sstream>
#include <cmath>
#include <string>
using namespace std;
class Rational {
public:
    Rational() {
        num = 0;
        den = 1;
    }
    Rational(int numerator, int denominator) {
        if (denominator == 0) throw invalid_argument("invalid_argument");
        else if (denominator < 0) {
            if (numerator < 0) {
                denominator = abs(denominator);
                numerator = abs(numerator);
            }
            else {
                denominator = abs(denominator);
                numerator = numerator - 2 * numerator;
            }
        }
        if (numerator == 0) {
            denominator = 1;
        }
        int nod = Nod(abs(numerator), abs(denominator));
        num = numerator / nod;
        den = denominator / nod;
    }
    int Numerator() const {
        return num;
    }
    int Denominator() const {
        return den;
    }
private:
    int num;
    int den;
 
    int Nod(int a, int b) {
        while (a > 0 && b > 0) {
            if (a > b) {
                a %= b;
            }
            else {
                b %= a;
            }
        } //while
        return a + b;
    }
};
Rational operator / (Rational a, Rational b) {
    if (b.Numerator() == 0) throw domain_error("domain_error");
    return Rational((a.Numerator() * b.Denominator()), (a.Denominator() * b.Numerator()));
}
istream& operator >> (istream& stream, Rational& r) {
    //if (stream) return stream;
    int p, q;
    if (stream >> p && stream.ignore(1) && stream >> q) {
        r = { p, q };
    }
    return stream;
}
ostream& operator << (ostream& stream, const Rational& r) {
    stream << r.Numerator() << "/" << r.Denominator();
    return stream;
}
int main() {
    try {
        Rational r(1, 0);
        cout << "Doesn't throw in case of zero denominator" << endl;
        return 1;
    }
    catch (invalid_argument&) {
    }
 
    try {
        auto x = Rational(1, 2) / Rational(0, 1);
        cout << "Doesn't throw in case of division by zero" << endl;
        return 2;
    }
    catch (domain_error&) {
    }
 
    cout << "OK" << endl;
    return 0;
}
С исключениями вроде просто всё
Всего комментариев 2
Комментарии
  1. Старый комментарий
    Аватар для Avazart
    C++
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
    try 
    {
          Rational r(1, 0);
          auto x = Rational(1, 2) / Rational(0, 1);
    }
    catch (const invalid_argument& e) 
    {
      cerr<< e.what() <<endl;
    }
    catch (const domain_error& e) 
    {
      cerr<< e.what() <<endl;
    }
    Или еще проще используя базовый класс std::logic_error
    C++
    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    try 
    {
          Rational r(1, 0);
          auto x = Rational(1, 2) / Rational(0, 1);
    }
    catch (const std::logic_error& e) 
    {
      cerr<< e.what() <<endl;
    }
    Запись от Avazart размещена 18.04.2018 в 11:54 Avazart вне форума
  2. Старый комментарий
    Аватар для Avazart
    C++
    1
    2
    3
    4
    
    Rational() {
            num = 0;
            den = 1;
        }
    Как насчет использовать список инициализации и перегрузить больше золота операторов?
    Например относительно int

    И деление на 0 мне кажется тут вполне уместно ибо сама операция / 0 по факту не происходит,
    Так что вероятно можно обойтись без проверки нуля в знаменателе.

    (1/2) / (0/1) = (1/0) т.е. бесконечность т.е. вроде INF / -INF для float.
    Запись от Avazart размещена 07.05.2018 в 10:10 Avazart вне форума
    Обновил(-а) Avazart 07.05.2018 в 13:29
 
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru