I want to know how to apply exception handling when the top variable reaches to a value -1 (no element left to pop). Currently, I am using cout to nofity the user about the stack underflow and returning 0, which is not a good practice. What improvement overall can be made to this pop function and how to notify user and handle the exception when stack reaches a state of underflow.
int Mystack::pop()
{
if (isEmpty())
{
std::cout << "Stack Underflow" << std::endl;
}
else
{
std::cout << "The popped element is" << A[top];
return A[top--];
}
return 0;
}
The Main Section :
case 4:
std::cout << "POP the element" << std::endl;
s1.pop();
break;
You can throw an out_of_range exception:
#include <stdexcept>
int Mystack::pop()
{
if (isEmpty())
throw std::out_of_range("Stack Underflow");
std::cout << "The popped element is" << A[top];
return A[top--];
}
On the client side:
void foo()
{
Mystack ms;
//...
try
{
ms.pop();
}
catch (const std::out_of_range& oor)
{
std::cerr << "Out of Range error: " << oor.what() << '\n';
}
}
Edit: As the comments below mentioned, you can also derive your own exception from std::exception. Here is a simple example:
#include <stdexcept>
struct myStackException : public std::exception
{
const char *what() const noexcept { return "Stack Overflow"; }
};
int Mystack::pop()
{
if (isEmpty())
throw myStackException();
std::cout << "The popped element is" << A[top];
return A[top--];
}
Live (dummy) example: http://ideone.com/ZyqiQ0
Re
” What improvement overall can be made to this pop function
You can
Make it void to make it more exception safe for other item types.
With the current design, if copying of the popped item fails, then there is no way to recover.
Remove internal output.
assert that the underflow doesn't occur, so that this can be caught in testing.
Thus,
void Mystack::pop()
{
assert( top > 0 );
--top;
}
Wow, what a simplification – and now more exception safe too!
As an alternative to the assert you can throw an exception. That's better than the original, but absolutely not better than the assert. It moves correctness issues into the runtime domain, to be handled and perhaps worked around by each caller site.
The benefit of using C++ exceptions is that error handling code can be separated from user code, alleviating the need for code to be littered with error handling code that is common in C programs. Throwing an exception also offers a solution to returning a invalid value in the error case
if( s1.pop() == 0 ){
// is this an error or not?
}
Exceptions can be added to your code like so, by taking advantage in the generic exceptions in the
#include <stdexcept>
header file.
int Mystack::pop()
{
if (isEmpty())
{
throw std::range_error("nothing to pop");
}
std::cout << "The popped element is" << A[top];
return A[top--];
}
Then you add a try/catch block to the appropriate code, perhaps with
case 4:
std::cout << "POP the element" << std::endl;
try{
s1.pop();
}
catch(const std::range_error& e)
{
std::cerr << "unable to pop!\n";
// error handling code
}
break;
Another solution, particularly appropriate when errors aren't as exceptional, such as with file I/O is more intrusive to the user code, but offers a better solution than returning an arbitrary value
int Mystack::pop(int& value)
{
if( isEmpty() )
{
return 1;
}
std::cout << "The popped element is" << A[top];
value = A[top--];
return 0
}
And then your code becomes
case 4:
std::cout << "POP the element" << std::endl;
{
int value;
if( s1.pop(value) == 1 ){
// error code
}
}
break;
Related
int At(int i, int j) const {
try {
if (i >= m.size() || j >= m[0].size())
throw out_of_range("out_of_range");
return m.at(i).at(j);
}
catch (exception& e) {
cout << e.what() << endl;
}
}
int& At(int i, int j) {
try {
if (i >= m.size() || j >= m[0].size())
throw out_of_range("out_of_range");
return m.at(i).at(j);
}
catch (exception& e) {
cout << e.what() << endl;
}
}
int main() {
Matrix one, two(2, 3);
cout << two;
one.Reset(0, 0);
cout << one.At(4, 4);
return 0;
}
in this code must be printed exception: out_of_range, but in my case it is :
out_of_range
-244281
What are this number and how can I remove it from output?
If the exception is thrown, then the catch handler prints the message ("out_of_range") and then the function continues on like nothing happened.
The problem is that this "continue on" leads to the functions ending without you returning anything, leading to undefined behavior when you try to print this non-return value.
If you declare a function to return anything, the you must return something.
With that said, catching the exception in the At function makes no sense. And considering that one of the variants return a reference, it's very hard to return a "value" since you can't have "null" references.
The solution then is not to have the try-catch at all in the functions, but let the caller of the function handle any possible exception.
int& At(int i, int j) {
// ...
catch (exception& e) {
cout << e.what() << endl;
}
}
The exception is caught and printed ...and then At() returns normally.
Your compiler should've warned you about returning from a non-void function without returning a value.
In your main():
cout << one.At(4, 4);
So, now this attempts to interpreted the value returned from At() as a reference to some int. Nothing was returned, so this is undefined behavior, and you can get any random junk printed here. Or your program can crash. You have no logical expectations, any more.
In question about scope of exception it is stated by Aj. that throw and catch clauses will create copies of the exception (unless reference is used I guess)
I tried myself a small toy code and I don't understand the result. here :
//g++ 7.4.0
#include <iostream>
using namespace std;
struct Some_error {
Some_error(float code):err_code(code){ cout << "Some_error(" << err_code << ")\n"; }
~Some_error() { cout << "~Some_error(" << err_code << ")\n"; }
Some_error(const Some_error& o):err_code(o.err_code+0.1) { cout << "Some_error(copy::" << err_code << ")\n"; }
Some_error(Some_error&& o):err_code(std::move(o.err_code)+.01){ cout << "Some_error(move::" << err_code << ")\n"; }
int get_code() const { return err_code; }
private : float err_code;
};
int do_task() {
if ( false ) return 42; else throw Some_error {1};
cout << "end do_task\n" ;
}
void taskmaster(){
try { auto result = do_task(); cout << "the answer is " << result << "\n" ; }
catch (Some_error e) { cout << "catch Some_error : " << e.get_code() << "\n" ; }
cout << "end taskmaster\n" ;
}
int main() { taskmaster(); }
the trace I get is as follows :
Some_error(1)
Some_error(copy::1.1)
catch Some_error : 1
~Some_error(1.1)
~Some_error(1)
end taskmaster
Now first, as I used no reference here, according to Aj., I would expect 2 copies to happen.
And second, there was a copy, that set err_code to 1.1, but the display is still 1.
Remark: just to be complete, I changed the catch to : catch(Some_error& e),
and then the trace looks fine to me :
Some_error(1)
catch Some_error : 1
~Some_error(1)
end taskmaster
I would expect 2 copies to happen.
Why? Only one copy is made by the catch block. Where would the second copy happen?
set err_code to 1.1, but the display is still 1.
Because get_code returns an int, so the floating point value gets truncated.
I am analyzing part of code that was part of my lectures.
I have managed to compile it but I cannot understand:
why does my program output "Wyjatek" and 0 instead of "WyjatekNieoznaczony"?
I was pretty sure WyjatekNieoznaczony() should be thrown because a=0 and b=0 as well. Right now i am a little bit confused.
Could you help me, please?
class Wyjatek {};
class WyjatekBledny : public Wyjatek {};
class WyjatekNieoznaczony : public Wyjatek {};
double f(double a, double b) {
if (b == 0) {
if (a == 0)
throw WyjatekNieoznaczony();
else
throw WyjatekBledny();
}
return a / b;
}
double g(double a, double b) throw (int) {
try {
return f(a, b);
}
catch (WyjatekBledny) {
cout << "Wyjatek bledny" << endl;
throw 1;
}
catch (Wyjatek) {
cout << "Wyjatek" << endl;
}
catch (WyjatekNieoznaczony) {
cout << "Wyjatek nieoznaczony" << endl;
throw;
}
return 0;
}
int main()
{
double a = 0, b = 0;
try {
cout << g(a, b) << endl;
}
catch (...)
{
cout << "Inny wyjatek" << endl;
}
system("pause");
return 0;
}
Yes indeed a WyjatekNieoznaczony is thrown, but at the catch site, catch (Wyjatek) { is a match (due to the inheritance) so it's caught there.
A catch site is more like an if else block in behaviour - with each catch possibility being considered in the order they are written - rather than a switch block where you can put the labels in any order you like.
Note also that it's a good idea to catch exceptions by const reference than by value, else you can suffer the pitfalls of object slicing.
If you enabled (and read) compiler warnings, you would've encountered the following diagnostic:
warning: exception of type 'WyjatekNieoznaczony' will be caught [...] by earlier handler for 'Wyjatek'.
This basically means that WyjatekNieoznaczony, by inheriting from Wyjatek, will be first caught by catch(Wyjatek) clause, since it's convertible. The problem is that due to object slicing, it will lose its Nieoznaczonyness.
What I suggest is to reorder the catch clauses so the possibility of slicing disappears (in this case):
catch (WyjatekBledny) {
cout << "Wyjatek bledny" << endl;
throw 1;
}
catch (WyjatekNieoznaczony) {
cout << "Wyjatek nieoznaczony" << endl;
throw;
}
catch (Wyjatek) {
cout << "Wyjatek" << endl;
}
So I have an upcoming assignment dealing with exceptions and using them in my current address book program that most of the homework is centered around. I decided to play around with exceptions and the whole try catch thing, and using a class design, which is what I will eventually have to do for my assignment in a couple of weeks. I have working code that check the exception just fine, but what I want to know, is if there is a way to standardize my error message function, (i.e my what() call):
Here s my code:
#include <iostream>
#include <exception>
using namespace std;
class testException: public exception
{
public:
virtual const char* what() const throw() // my call to the std exception class function (doesn't nessasarily have to be virtual).
{
return "You can't divide by zero! Error code number 0, restarting the calculator..."; // my error message
}
void noZero();
}myex; //<-this is just a lazy way to create an object
int main()
{
void noZero();
int a, b;
cout << endl;
cout << "Enter a number to be divided " << endl;
cout << endl;
cin >> a;
cout << endl;
cout << "You entered " << a << " , Now give me a number to divide by " << endl;
cin >> b;
try
{
myex.noZero(b); // trys my exception from my class to see if there is an issue
}
catch(testException &te) // if the error is true, then this calls up the eror message and restarts the progrm from the start.
{
cout << te.what() << endl;
return main();
}
cout <<endl;
cout << "The two numbers divided are " << (a / b) << endl; // if no errors are found, then the calculation is performed and the program exits.
return 0;
}
void testException::noZero(int &b) //my function that tests what I want to check
{
if(b == 0 ) throw myex; // only need to see if the problem exists, if it does, I throw my exception object, if it doesn't I just move onto the regular code.
}
What I would like to be able to do is make it so my what() function can return a value dependent on what type of error is being called on. So for instance, if I were calling up an error that looked a the top number,(a), to see if it was a zero, and if it was, it would then set the message to say that "you can't have a numerator of zero", but still be inside the what() function. Here's an example:
virtual const char* what() const throw()
if(myex == 1)
{
return "You can't have a 0 for the numerator! Error code # 1 "
}
else
return "You can't divide by zero! Error code number 0, restarting the calculator..."; // my error message
}
This obviously wouldn't work, but is there a way to make it so I'm not writing a different function for each error message?
Your code contains a lot of misconceptions. The short answer is yes, you can change what() in order to return whatever you want. But let's go step by step.
#include <iostream>
#include <exception>
#include <stdexcept>
#include <sstream>
using namespace std;
class DivideByZeroException: public runtime_error {
public:
DivideByZeroException(int x, int y)
: runtime_error( "division by zero" ), numerator( x ), denominator( y )
{}
virtual const char* what() const throw()
{
cnvt.str( "" );
cnvt << runtime_error::what() << ": " << getNumerator()
<< " / " << getDenominator();
return cnvt.str().c_str();
}
int getNumerator() const
{ return numerator; }
int getDenominator() const
{ return denominator; }
template<typename T>
static T divide(const T& n1, const T& n2)
{
if ( n2 == T( 0 ) ) {
throw DivideByZeroException( n1, n2 );
}
return ( n1 / n2 );
}
private:
int numerator;
int denominator;
static ostringstream cnvt;
};
ostringstream DivideByZeroException::cnvt;
In the first place, runtime_error, derived from exception, is the adviced exception class to derive from. This is declared in the stdexcept header. You only have to initialize its constructor with the message you are going to return in the what() method.
Secondly, you should appropriately name your classes. I understand this is just a test, but a descriptive name will always help to read and understand your code.
As you can see, I've changed the constructor in order to accept the numbers to divide that provoked the exception. You did the test in the exception... well, I've respected this, but as a static function which can be invoked from the outside.
And finally, the what() method. Since we are dividing two numbers, it would be nice to show that two numbers that provoked the exception. The only way to achieve that is the use of ostringstream. Here we make it static so there is no problem of returning a pointer to a stack object (i.e., having cnvt a local variable would introduce undefined behaviour).
The rest of the program is more or less as you listed it in your question:
int main()
{
int a, b, result;
cout << endl;
cout << "Enter a number to be divided " << endl;
cout << endl;
cin >> a;
cout << endl;
cout << "You entered " << a << " , Now give me a number to divide by " << endl;
cin >> b;
try
{
result = DivideByZeroException::divide( a, b );
cout << "\nThe two numbers divided are " << result << endl;
}
catch(const DivideByZeroException &e)
{
cout << e.what() << endl;
}
return 0;
}
As you can see, I've removed your return main() instruction. It does not make sense, since you cannot call main() recursively. Also, the objective of that is a mistake: you'd expect to retry the operation that provoked the exception, but this is not possible, since exceptions are not reentrant. You can, however, change the source code a little bit, to achieve the same effect:
int main()
{
int a, b, result;
bool error;
do {
error = false;
cout << endl;
cout << "Enter a number to be divided " << endl;
cout << endl;
cin >> a;
cout << endl;
cout << "You entered " << a << " , Now give me a number to divide by " << endl;
cin >> b;
try
{
result = DivideByZeroException::divide( a, b ); // trys my exception from my class to see if there is an issue
cout << "\nThe two numbers divided are " << result << endl;
}
catch(const DivideByZeroException &e) // if the error is true, then this calls up the eror message and restarts the progrm from the start.
{
cout << e.what() << endl;
error = true;
}
} while( error );
return 0;
}
As you can see, in case of an error the execution follows until a "proper" division is entered.
Hope this helps.
You can create your own exception class for length error like this
class MyException : public std::length_error{
public:
MyException(const int &n):std::length_error(to_string(n)){}
};
class zeroNumerator: public std::exception
{
const char* what() const throw() { return "Numerator can't be 0.\n"; }
};
//...
try
{
myex.noZero(b); // trys my exception from my class to see if there is an issue
if(myex==1)
{
throw zeroNumerator(); // This would be a class that you create saying that you can't have 0 on the numerator
}
}
catch(testException &te)
{
cout << te.what() << endl;
return main();
}
You should always use std::exception&e. so do
catch(std::exception & e)
{
cout<<e.what();
}
You should consider a hierarchy of classes.
The reason for it might not be obvious when trying to use exceptions just for transferring a string, but actual intent of using exceptions should be a mechanism for advanced handling of exceptional situations. A lot of things are being done under the hood of C++ runtime environment while call stack is unwound when traveling from 'throw' to corresponded 'catch'.
An example of the classes could be:
class CalculationError : public std::runtime_error {
public:
CalculationError(const char * message)
:runtime_error(message)
{
}
};
class ZeroDeviderError : public CalculationError {
public:
ZeroDeviderError(int numerator, const char * message)
: CalculationError(message)
, numerator (numerator)
{
}
int GetNumerator() const { return numerator; }
private:
const int numerator;
};
Providing different classes for the errors, you give developers a chance to handle different errors in particular ways (not just display an error message)
Providing a base class for the types of error, allows developers to be more flexible - be as specific as they need.
In some cases, they might want to be specific
} catch (const ZeroDividerError & ex) {
// ...
}
in others, not
} catch (const CalculationError & ex) {
// ...
}
Some additional details:
You should not create objects of your exceptions before throwing in the manner you did. Regardless your intention, it is just useless - anyway, you are working with a copy of the object in the catch section (don't be confused by access via reference - another instance of the exception object is created when throwing)
Using a const reference would be a good style catch (const testException &te) unless you really need a non-constant object.
Also, please note that the type (classes) used for exceptions are not permitted to throw exceptions out of their copy constructors since, if the initial exception is attempted to be caught by value, a call of copy constructor is possible (in case is not elided by the compiler) and this additional exception will interrupt the initial exception handling before the initial exception is caught, which causes calling std::terminate.
Since C++11 compilers are permitted to eliminate the copying in some cases when catching, but both the elision is not always sensible and, if sensible, it is only permission but not obligation (see https://en.cppreference.com/w/cpp/language/copy_elision for details; before C++11 the standards of the language didn’t regulate the matter).
Also, you should avoid exceptions (will call them the additional) to be thrown out of constructors and move constructors of your types (classes) used for exceptions (will call them initial) since the constructors and move constructors could be called when throwing objects of the types as initial exceptions, then throwing out an additional exception would prevent creation of an initial exception object, and the initial would just be lost. As well as an additional exception from a copy constructor, when throwing an initial one, would cause the same.
I wrote a very simple solution however someone laughed and found a flaw as shown here http://ideone.com/IcWMEf
#include <iostream>
#include <ostream>
#include <functional>
#include <exception>
using namespace std;
// Wrong scope(failure)
class FailBlockT
{
typedef function<void()> T;
public:
T t;
FailBlockT(T t)
{
this->t=t;
}
~FailBlockT()
{
if (std::uncaught_exception())
{
t();
}
}
};
struct Test
{
~Test()
{
try
{
FailBlockT f([]()
{
cout << "failure" << endl;
});
// there is no any exception here, but "failure" is printed.
// See output below
}
catch(...)
{
cout << "some exception" << endl;
}
}
};
int main()
{
try
{
Test t;
throw 1;
}
catch(int){}
return 0;
}
In short the problem is my code looks at std::uncaught_exception(). When an exception is thrown and a normal destructor is executed. If i use scope failure there it will look at std::uncaught_exception() and think the object scope is lost due to exception rather then simply walking out of scope.
I can't think of any good solutions to differentiate leaving scope normally VS having an exception thrown IN it. Yes i know throwing is a bad idea in dtors BUT thats why I fail to notice this problem, because I never throw in exceptions.
How do I differentiate/solve this?
No exception was thrown but it thinks it has.
An exception was thrown, just not from right there.
There is no mechanism in C++11 to ask, "Was an exception thrown from code just below me, but not from code elsewhere in the call-stack?" std::uncaught_exception is doing exactly what it is supposed to do: say whether there is an exception currently in the process of being resolved at the time the function is called. And there is, so it returns true.
C++17 adds std::uncaught_exceptions (note the plural), which can be used to detect the difference. With such a tool, you can make your FailBlock object work:
template<typename Func>
class FailBlockT
{
private:
int e_count_;
T t_;
public:
FailBlockT(T t) : e_count_(std::uncaught_exceptions()), t_(t) {}
FailBlock(const FailBlock &) = delete; //The type should not be mobile.
~FailBlockT()
{
if (std::uncaught_exceptions() != e_count_)
{
t_();
}
}
};
std::uncaught_exceptions() returns the number of exceptions that are provoking stack unwinding at the time the call was made. If the number is the same during the constructor and destructor of an object (assuming it's a stack object), then the destructor is not being called due to an exception being thrown through where this type was used.
But without this tool, it, there's not much you can do to differentiate between an exception provoking the exiting of the scope rather than exiting a scope when exception unwinding just happens to be going on. So you're going to have to bite the bullet and catch the exception like everyone else.
Or just don't put this FailBlock thing in destructors. It seems to me that those should go directly into regular functions that can actually throw (and destructors should never throw). It seems to me that you're worried about a corner case that doesn't make any real sense.
I can't think of any good solutions to differentiate leaving scope normally VS having an exception thrown IN it.
Check stack_unwinding library - I have implemented scope(failure) and scope(success) features in C++.
It is based on platform specific function uncaught_exception_count. It is similar to std::uncaught_exception from standard library, but instead of boolean result it returns unsigned int showing current count of uncaught exceptions.
Currently it is tested on {Clang 3.2, GCC 3.4.6, GCC 4.1.2, GCC 4.4.6, GCC 4.4.7, MSVC2005SP1, MSVC2008SP1, MSVC2010SP1, MSVC2012} x {x32, x64}.
In C++11 folowing syntax is available:
try
{
int some_var=1;
cout << "Case #1: stack unwinding" << endl;
scope(exit)
{
cout << "exit " << some_var << endl;
++some_var;
};
scope(failure)
{
cout << "failure " << some_var << endl;
++some_var;
};
scope(success)
{
cout << "success " << some_var << endl;
++some_var;
};
throw 1;
} catch(int){}
{
int some_var=1;
cout << "Case #2: normal exit" << endl;
scope(exit)
{
cout << "exit " << some_var << endl;
++some_var;
};
scope(failure)
{
cout << "failure " << some_var << endl;
++some_var;
};
scope(success)
{
cout << "success " << some_var << endl;
++some_var;
};
}
In C++98 it is a bit more noisier:
try
{
cout << "Case #1: stack unwinding" << endl;
BOOST_SCOPE_EXIT(void) { cout << "exit" << endl; } BOOST_SCOPE_EXIT_END
SCOPE_FAILURE(void) { cout << "failure" << endl; } SCOPE_FAILURE_END
SCOPE_SUCCESS(void) { cout << "success" << endl; } SCOPE_SUCCESS_END
throw 1;
} catch(int){}
{
cout << "Case #2: normal exit" << endl;
BOOST_SCOPE_EXIT(void) { cout << "exit" << endl; } BOOST_SCOPE_EXIT_END
SCOPE_FAILURE(void) { cout << "failure" << endl; } SCOPE_FAILURE_END
SCOPE_SUCCESS(void) { cout << "success" << endl; } SCOPE_SUCCESS_END
}
Also, library has UNWINDING_AWARE_DESTRUCTOR feature. Example:
struct DestructorInClass
{
UNWINDING_AWARE_DESTRUCTOR(DestructorInClass,unwinding)
{
cout << "DestructorInClass, unwinding: "
<< ( unwinding ? "true" : "false" ) << endl;
}
};
However, there are some cases where UNWINDING_AWARE_DESTRUCTOR may give wrong results (though scope(success) and scope(failure) features are not affected by such issues).