How can I simplify this program? [closed] - c++

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 1 year ago.
Improve this question
I'm writing a program that finds the roots of a quadratic equation using exception handling and i'm wondering if there's a way I can simplify the program, I have a bunch of empty classes for the catch cases
// Program to solve quadratic equation
#include <iostream>
#include <cstdlib>
#include <cmath>
using namespace std;
class all_zero{
};
class negative{
};
class zero_division{
};
void roots(double a, double b, double c) throw (all_zero,negative,zero_division);
int main(){
double a, b, c; // coefficient of ax“2 + bx + c= 0
cout << "Enter the three coefficients \n";
cin >> a >> b >> c;
try
{
roots(a, b, c);
}
catch(all_zero) {cout << "All values are zero \n";}
catch(negative) {cout << "Square root of negative values is not defined \n";}
catch(zero_division) {cout << "Division by zero, not defined \n";}
return 0;
}
void roots(double a, double b, double c) throw (all_zero,negative,zero_division){
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;
cout << "The two roots are: "<< x1 <<" and " << x2 << endl;
}else{throw negative();}
}else{throw zero_division();}
}else{throw all_zero();}
}
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?

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";
}

My input:
Make sure the formula is correct. The /2*a part should be /(2*a).
Define an error category for your solver's errors and inherit more specific errors from that.
Remove unnessary tests (a== 0 && b== 0 && c==0). You already check if a == 0, so if a != 0 but b and c are, the solution will be 0, which should be valid.
Reverse the tests to not have to throw in an else. Throw early to not have deep nested if's.
Return the result, don't print it. I've added tweaks to make it possible to solve linear and complex equations too (in comments), but you can skip that if you want. This shows how you can return multiple values though.
Don't do forward declaration unless you really have to.
Read Why is using namespace std; considered bad practice?
More details in comments in the code
#include <cmath>
#include <cstdlib>
#include <iostream>
#include <stdexcept>
#include <tuple> // std::tuple - used for returning multiple values here
struct solver_error : std::runtime_error { // your solver's error category
using std::runtime_error::runtime_error;
};
struct unknown_error : solver_error {
unknown_error() : solver_error("x is unknown") {}
};
struct linear_error : solver_error {
linear_error() : solver_error("cant solve linear equation") {}
};
struct complex_error : solver_error {
complex_error() : solver_error("cant solve complex equation") {}
};
// add more exceptions to the solver_error exception category if needed
// now returns two values and a bool to indicate if the solution is complex
std::tuple<double, double, bool> solve_for_x(double a, double b, double c) {
if(a == 0) throw linear_error(); // throw early
/* ... or solve it as a linear equation:
if(a == 0) {
if(b == 0) throw unknown_error(); // both a and b == 0, x is unknown
double res = -c / b;
return {res, res, false}; // only one x and not complex
}
*/
double div = 2 * a;
double temp = b * b - 4 * a * c;
if(temp < 0) throw complex_error();
/* ... or solve it as a complex equation
if(temp < 0) {
double sqr = sqrt(-temp); // sqrt of the positive temp instead
return {-b / div, sqr / div, true}; // real, imaginary and complex==true
}
*/
// real quadratic
double sqr = sqrt(temp);
double x1 = (-b + sqr) / div; // corrected formula (div = 2*a)
double x2 = (-b - sqr) / div; // corrected formula
return {x1, x2, false}; // return the two values and complex==false
}
int main() {
// make the user aware of what the coefficients are for
std::cout << "Enter the three coefficients a, b and c in the equation\n"
"ax^2 + bx + c = 0\n";
double a, b, c;
try {
// check that extracting the numbers succeeds
if(not(std::cin >> a >> b >> c)) throw std::runtime_error("input error");
// get the three return values via structured bindings
auto [first, second, complex] = solve_for_x(a, b, c);
std::cout << "x = ";
if(complex) // complex quadratic
std::cout << first << " ± " << second << 'i';
else if(first == second) // linear
std::cout << first;
else // real quadratic
std::cout << '{' << first << ',' << second << '}';
std::cout << '\n';
} catch(const solver_error& ex) {
// catching the generic error category by "const&"
std::cerr << "Solver error: " << ex.what() << '\n';
return 1;
} catch(const std::runtime_error& ex) {
std::cerr << ex.what() << '\n';
return 1;
}
}

Related

C++ Handling super basic errors how should I do this?

double ctok(double c) // converts Celsius to Kelvin
{
if (c <= -273.15)
{
cout << "Temp too low.";
exit(1);
}
else {
double k = c + 273.15;
return k;
}
}
int main()
{
double c = 0;
cin >> c; // retrieve temperature to input variable
double k = ctok(c); // convecout << rt temperature
cout << k << '/n'; // print out temperature
}
So if c is smaller or equal to -273.15 I want to basically stop the program and I wanna do all this in the ctok function so I just check with an if statement and then use exit() but something here just seems off and I feel like this isn't a good way to handle it.. I've also heard using exit isn't really good but my only other idea is to handle this with exceptions:
So I add this function definition:
void error(string s)
{
throw runtime_error(s);
}
Then I can just do this:
double ctok(double c) // converts Celsius to Kelvin
{
if (c <= -273.15)
{
error("Temp too low.");
}
double k = c + 273.15;
return k;
}
int main()
{
try {
double c = 0;
cin >> c; // retrieve temperature to input variable
double k = ctok(c); // convecout << rt temperature
cout << k << '/n'; // print out temperature
}
catch (runtime_error a)
{
cout << a.what();
}
}
But this also feels a little overkill for handling such a simple error doesn't it? So I just wanna know is there like some good basic way to deal with such a basic error?
You could make ctok return bool and pass a pointer or reference to a variable and store the result:
bool ctok(double c, double *pr)
if( ! ctok( c, &k ) )
cout << "error\n";
or simply ctok() should throw itself the exception instead of a function that do nothing more than a throw...
IMO, both are simple solutions for a simple program, even with your 'error()' function.

Classes and Exception Handling In C++

I've run across a coding problem that I'm having trouble understanding (note the line tagged with //-):
#include <iostream>
using namespace std;
class X { };
class X0 { };
class X1: public X0 { };
class X2: public X1 { };
void f(int i) {
if (i == 0) {
throw X0();
} else if (i == 1) {
throw X1();
} else if (i == 2) {
throw X2();
} else {
throw X();
}
}
int main(int argc, char* argv[]) {
try {
f(0); //-
} catch (X1) {
cout << "A" << endl;
} catch (X2) {
cout << "B" << endl;
} catch (X0) {
cout << "C" << endl;
} catch (...) {
cout << "D" << endl;
}
}
The output of this code is C, as expected. If I change the tagged line to "f(1);" the output is A, also as expected.
However, if I change the tagged line to "f(2);" the answer is also A, and I'm not understanding why. I feel like it may have something to do with the scope of the destructors, but my attempts to find information on it haven't been successful because I'm not entirely sure what to study. Would anyone be able to explain what is happening here, or just the name of concept this problem is illustrating so I can research it? Any help is appreciated.
An X2 inherits from X1 and so "is" an X1, and the catch block for X1 is first so triggers before we reach the X2 one.
When i == 2 , you throw an X2, X2 is derived from X1.
The order of catches matter, you attempt to catch X1 first, X2 (what you threw) is an X1, so that is the catch that fires. You need to reorder your catches to catch the most specific first
However, if I change the tagged line to "f(2);" the answer is also A, and I'm not understanding why.
This is because X2 is subclass of X1.
When you call f(2) in try, f(2) throws X2. It seems like the exception should be caught in catch(X2). However, X2 is subclass of X1.
So the exception is caught in catch(X1) and the code inside catch prints A.
So if you want to see B when you call f(2), the code should be like this.
//skipped some code
int main(int argc, char* argv[]) {
try {
f(2); //-
} catch (X2) {
cout << "B" << endl;
} catch (X1) {
cout << "A" << endl;
} catch (X0) {
cout << "C" << endl;
} catch (...) {
cout << "D" << endl;
}
}
You should catch X2 before X1, as it is derived from X1, otherwise the catch for X1 catches X2 as well.
In Java this would have been a compilation error.
The type of exception is matched in the order of catch clauses under the matching rules (http://en.cppreference.com/w/cpp/language/try_catch):
T is an unambiguous public base class of E
X1 is public base class of X2 so it's a match.

separating decimal points into two integers

I have been given double x = 23.456; and two integer d and c.
I have to break it so that d gets the value 23 and c gets the value 456.
I thought of the following:-
int d;
d=(int)x;
but I cannot think of what to do with c as it is an integer and if i write
c=(x-d)*1000;
then it might be applicable for this case only and not for any other case.
Is there any way to get the number of digits after the decimal and then multiply it with equal number of zeros.
Please help!!!
You could repeatedly multiply it by 10, until there is nothing after decimal point.
double c = x - d;
while(c - floor(c) > 0.0)
{c *= 10;}
you may also need to #include <math.h> for floor function, which rounds down a number. e.g. floor(4.9) returns 4.0
Floating point calculations are little bit tricky in C++ (same is true for Java and other languages). You should avoid their direct comparison and do some other stuff to get predictable result when using them, consider:
double d1=1.1;
double d2= d1 / 10.0;
if(d2==0.11)cout << "equals" << endl;
else cout << "not equals" << endl; //result is "not equals"
d1=1.99;
float f1=0.01f;
double d3=d1+f1;
if(d3==2.0)cout << "equals" << endl;
else cout << "not equals" << endl; //result is "not equals"
d1=1.99;
d2=0.01;
d3=d1+d2-2.0;
if(d3==0.0)cout << "equals" << endl;
else cout << "not equals" << endl; //result is "not equals"
As for practical solution of the problem I can suggest 2 variants:
Var 1 is to use a function that allows to specify number of digits:
#include <iostream>
#include <cmath>
using namespace std;
void split_double(const double value, int& i_part, int& r_part,
const int max_digits_after_dp, int min_digits_after_dp){
auto powerOfTenL = [](int power){ int result = 1;
for(int i=0;i<power;++i)result *= 10;
return result;
};
//Get integral part
i_part = (int)value;
double temp = (value-i_part);
double pOfTen = powerOfTenL(max_digits_after_dp);
temp *= pOfTen;
//Get real part
r_part = round(temp);
//Remove zeroes at the right in real part
int num_of_d = max_digits_after_dp;
if(min_digits_after_dp>max_digits_after_dp)
min_digits_after_dp=max_digits_after_dp;
while (num_of_d>min_digits_after_dp) {
//If the number is divisible by 10, divide it by 10
if(0==(r_part%10)) { r_part /=10; num_of_d--;
}
else break; //Last digit is not 0
}
}
int main(int argc, char *argv[])
{
double value = 10.120019;
int ipart,rpart;
const int digitsMax = 6;
const int digitsMin = 3;
split_double(value,ipart,rpart,digitsMax,digitsMin);
cout<<"Double " <<value << " has integral part " <<ipart
<<" and real part "<<rpart<<endl;
return 0;
}
Second variant to solve the problem is to use C/C++ formatting functions like vsprintf and then split the resulting string.

error: called object type 'double' is not a function or function pointer

I am relatively new to c++ programming, I have an assignment to code the Newton Raphson method however I have the error error:
called object type 'double' is not a function or function pointer
This error appears when I am trying to compile my code. I tried some basic changes to assign pointer but I probably did it in the wrong way, my code is printed below, can anybody explain how can I overcome this?
#include <iostream>
#include <math.h>
using namespace std;
double f(double x); //this is f(x)
double f(double x) {
double eq1 = exp(x) + pow(x,3) + 5;
return eq1;
}
double f1(double x); //this is the first derivative f'(x)
double f1(double x) {
double eq2 = exp(x) + 3*pow(x,2);
return eq2;
}
int main() {
double x, xn, f, f1, eps;
cout << "Select first root :" << '\n'; //Here we select our first guess
cin >> xn;
cout << "Select Epsilon accuracy :" << '\n';
cin >> epsi;
f = f(x);
f1 = f1(x);
cout << "x_n" << " " << "x_(n+1)" << " " << "|x_(n+1) - x_1|" << '\n';
do {
x = xn; //This is the first iteneration step where x takes the value of the last itenarated (known) root xn
f = f(x);
f1 = f1(x);
xn = x - (f/f1); //this the formula that sets the itenaration going
cout << x << " " << xn << " " << fabs(xn - x) << '\n';
}
while( fabs(xn - x) < epsi ); //If |x_(n+1) - x_n| is smaller than the desired accurcay than the itenaration continues
cout << "The root of the equation is " << xn << '\n';
return 0;
}
Thank you
You have local variables with the same name as the functions, thus
f = f(x);
f1 = f1(x);
cannot work.
Rename either the functions or the variables. Anyhow single letter variable/function names are not nice. Use descriptive names. You (or anybody else) taking a look at the code after some weeks will be thankful for that.
PS: you also dont need the forward declarations. And the functions can be written a bit shorter:
//double f(double x); // this you dont need
double f(double x) {
return exp(x) + pow(x,3) + 5;
}
Also using namespace std; is considered bad practice. In this case it does little to no harm, but you better get rid of this bad habit before it does matter.
Last but not least you should format your code properly. This
while( fabs(xn - x) < epsi );
looks very nasty, because it seems to be an infinite loop. I almost never use the do-while loop, however, I suggest you to write it like this:
do {
// ...
} while ();
because usually whenever you see a while with a ; in the same line you should start to panic ;) (while loops are much more common than do-while and errors caused by a ; after the condition in a while loop can be a pain in the a** to debug)
You are attempting to use functions called f and f1 and doubles called f and f1. If you call the variables or the function something else, then you can resolve the error. It would be good coding practice to give these variables better names that tell the reader what they do and avoid mistakes like this one.
There were several errors in your code. I made it compilable:
#include <iostream>
#include <math.h>
using namespace std;
double func(double x); //this is f(x)
double func(double x) {
double eq1 = exp(x) + pow(x,3) + 5;
return eq1;
}
double func1(double x); //this is the first derivative f'(x)
double func1(double x) {
double eq2 = exp(x) + 3*pow(x,2);
return eq2;
}
int main() {
double x, xn, f, f1, eps;
cout << "Select first root :" << '\n'; //Here we select our first guess
cin >> xn;
cout << "Select Epsilon accuracy :" << '\n';
cin >> eps;
f = func(x);
f1 = func1(x);
cout << "x_n" << " " << "x_(n+1)" << " " << "|x_(n+1) - x_1|" << '\n';
do {
x = xn; //This is the first iteneration step where x takes the value of the last itenarated (known) root xn
f = func(x);
f1 = func1(x);
xn = x - (f/f1); //this the formula that sets the itenaration going
cout << x << " " << xn << " " << fabs(xn - x) << '\n';
}
while( fabs(xn - x) < eps ); //If |x_(n+1) - x_n| is smaller than the desired accurcay than the itenaration continues
cout << "The root of the equation is " << xn << '\n';
return 0;
}
The main problems were:
you defined the variable f with the same name of the f(x) function (the same error was repeated for the f'(x) function) and
you declared the eps variable to represent epsilon in your program but you tried to access to it several times by calling it epsi.

In c++ how to avoid print message when I use function which has cout?

If i have two functions A and B, A will print message when we use A. B will use A, but when I use B, I do not want to print anything. How can I do this?
double CTriangle::perimeter() const{
double D = Distance(A, B) + Distance(A, C) + Distance(B, C);
cout << "Perimeter of this triangle is: " << D << endl;
return D;
}
double CTriangle::area() const{
double p = this->perimeter() / 2;
double Area = sqrt(p * (p - Distance(A, B)) * (p - Distance(A, C)) * (p - Distance(B, C)));
cout << "Area of this triangle is: " << Area << endl;
return Area;
}
How about adding a parameter to A(), e.g.
void A(bool verbose = true)
{
if (verbose) cout << "Hello world!" << endl;
}
void B()
{
A(false);
}
int main()
{
A(); // outputs "Hello world!"
B(); // calls A, but no output
return 0;
}
Assuming you don't have any control over the function which does the printing, you can put std::cout into a state where it won't print anything, e.g.:
std::cout.setstate(std::ios_base::failbit); // set error flag, disabling output
double d = this->perimeter();
std::cout.clear(); // clear flags, reenabling output
You can reasonably view the stream state a resource, i.e., it may be reasonable to use RAII to make sure the stream's state gets restored.
If you can change the function which does the unwanted output, I'd recommend rewriting this function to become two functions:
One function which doesn't do any logging and implements the core functionality.
Another function which does logging and calls the other function for the actual functionality.