Note that the dynamic excpetion specification you are using is deprecated in C++11 and removed in C++17:
void roots(double a, double b, double c) throw (all_zero,negative,zero_division)
// ^^
You can just remove it.
using namespace std;
is considered bad practice.
Do not use std::endl
to add a newline. std::endl
adds a new line and flushes the stream. Most of the time this is unnecessary. Use '\n'
to add a newline.
Is there a way I can make it so i dont have just empty classes or a way to put them into maybe a struct?
Actually, I don't see the bad about having seperate classes for the different types of exceptions. The downside of your approach is that the "what" is in the catch
, not part of the exception or coming from where the exception occured. I'll show you the first (message is part of the type) and hope you will see how to realize the latter (message is from where the exception is thrown).
You can inherit from std::runtime_error
which offers a what()
method that returns a string passed to the constructor. This also makes it easier for others to catch your exceptions, because std::runtime_error
in turn inherits from std::excpetion
which is the base class of all standard exceptions:
// Program to solve quadratic equation
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <stdexcept>
struct all_zero : std::runtime_error {
all_zero() : std::runtime_error("All values are zero") {}
};
struct negative : std::runtime_error {
negative() : std::runtime_error("Square root of negative values is not defined") {}
};
struct zero_division : std::runtime_error {
zero_division() : std::runtime_error("Division by zero, not defined") {}
};
void roots(double a, double b, double c);
int main(){
double a, b, c; // coefficient of ax“2 + bx + c= 0
std::cout << "Enter the three coefficients \n";
std::cin >> a >> b >> c;
try
{
roots(a, b, c);
}
catch(std::runtime_error& ex) {std::cout << ex.what() << '\n';}
return 0;
}
void roots(double a, double b, double c) {
double x1, x2; // The two roots
double temp;
if(!(a== 0 && b== 0 && c==0)){
if(a != 0){
temp = b*b - 4*a*c;
if(temp >= 0){
x1 =(-b + sqrt(temp))/2*a;
x2 = (-b - sqrt(temp))/2*a;
std::cout << "The two roots are: "<< x1 <<" and " << x2 << "\n";
}else{throw negative();}
}else{throw zero_division();}
}else{throw all_zero();}
}
Live Demo
Note that exceptions should be catched as reference, otherwise there will be object slicing when the exception is derived. And as in general you don't know what type of exception you will catch, you need to be careful to avoid that.
Alternatively you could use a more general exception type (roots_exception
?) and instead of hardcoding the "what" pass it to the constructor when you throw
it.
There is probably more you can improve, for which I suggest you https://codereview.stackexchange.com/.
PS: I tried to keep style aside, though one more thing you should change is to return the result from the function, instead of just printing it to the screen. If you want to use the result for other calcualtions you currently cannot. Perhaps you were puzzled how to return two values. std::pair
makes that simple:
std::pair<double,double> roots(...) {
// ...
return {x1,x2};
}
and then:
try {
auto result = roots(a,b,c);
std::cout << "The two roots are: "<< result.first <<" and " << result.second << "\n";
}