try
{
bool numericname=false;
std::cout <<"\n\nEnter the Name of Customer: ";
std::getline(cin,Name);
std::cout<<"\nEnter the Number of Customer: ";
std::cin>>Number;
std::string::iterator i=Name.begin();
while(i!=Name.end())
{
if(isdigit(*i))
{
numericname=true;
}
i++;
}
if(numericname)
{
throw "Name cannot be numeric.";
}
} catch(string message)
{
cout<<"\nError Found: "<< message <<"\n\n";
}
Why am I getting unhandled exception error ? Even after I have added the catch block to catch thrown string messages?
"Name cannot be numeric." is not a std::string, it's a const char*, so you need to catch it like this:
try
{
throw "foo";
}
catch (const char* message)
{
std::cout << message;
}
To catch "foo" as std::string you need to throw/catch it like this:
try
{
throw std::string("foo");
}
catch (std::string message)
{
std::cout << message;
}
You should send an std::exception instead, like throw std::logic_error("Name cannot be numeric")
you could then catch it with polymorphsim and the underlying type of your throw will no more be a problem :
try
{
throw std::logic_error("Name cannot be numeric");
// this can later be any type derived from std::exception
}
catch (std::exception& message)
{
std::cout << message.what();
}
Related
So I've got a program with two exception. In both cases, I'd like to throw a string that can be caught in the main function and used in an error message. However, from what I know about them
try {
...
} catch(string msg) {
cerr << "..." << msg << "..." << endl;
} catch (string msg2) {
cerr << "..." << msg2 << "..." << endl;
}
isn't allowed. Is there any way I could do the above or something like it?
Thanks
I see two use cases:
1. You want two distinct types of errors.
Add exception classes derived from std::exception
class MyException1 : public std::exception
{
std::string message;
public:
MyException1(std::string const &what_arg) : message(what_arg) {}
MyException1(char const * what_arg) : message(what_arg) {}
const char* what() const { return message.c_str(); }
};
class MyException2 : public std::exception
{
std::string message;
public:
MyException2(std::string const &what_arg) : message(what_arg) {}
MyException2(char const * what_arg) : message(what_arg) {}
const char* what() const { return message.c_str(); }
};
and catch those:
try
{
int a = 5;
// do stuff
if (a == 7)
{
throw MyException1("Error 1 occured in because a == 7.");
}
else if (a == 5)
{
throw MyException1("Error 1 occured because a == 5.");
}
// do more stuff
if (a == 22)
{
throw MyException2("Error 2 occured in because a == 22.");
}
else if (a == 575)
{
throw MyException2("Error 2 occured because a == 575.");
}
}
catch (MyException1 &ex)
{
std::cout << "Exception 1: " << ex.what() << "\n";
}
catch (MyException2 &ex)
{
std::cout << "Exception 2: " << ex.what() << "\n";
}
Note: This is an easy but not the best design for a custom exception since std::string may throw and your program will be terminated.
2. You want two different error messages:
Use the appropriate type of exception from <stdexcept> header:
try
{
int a = 5;
// do stuff
if (a == 7)
{
throw std::runtime_error("Error 1 occured because a == 7.");
}
else if (a == 5)
{
throw std::runtime_error("Error 2 occured because a == 5.");
}
}
catch (const std::exception &ex)
{
std::cout << "Exception: " << ex.what() << "\n";
}
Note: The behaviour of case 1 can be emulated in case 2 without own types if the only desired behaviour is different output:
try
{
int a = 5;
// do stuff
if (a == 7)
{
throw std::runtime_error("Exception 1: Error 1 occured in because a == 7.");
}
else if (a == 5)
{
throw std::runtime_error("Exception 1: Error 1 occured because a == 5.");
}
// do more stuff
if (a == 22)
{
throw std::runtime_error("Exception 2: Error 2 occured in because a == 22.");
}
else if (a == 575)
{
throw std::runtime_error("Exception 2: Error 2 occured because a == 575.");
}
}
catch (const std::exception &ex)
{
std::cout << ex.what() << "\n";
}
Use std::runtime_error it has a constructor that takes a string. So pass it a different value when it is throw.
throw runtime_error( "msg1");
...
throw runtime_error("msg2");
Then when you catch just print the message in the object
...
catch( exception& e ){
cout << e.what() << endl;
}
First: Your compiler is supposed to issue a warning for that, because, the second catch will never be executed, because they are of exact signatures. Besides, you cannot have a second exception being thrown while the first is active ( exception thrown during stack unwinding that hasn't entered a catch block yet), else, the runtime will terminate your program.
Secondly: prefer to catch your exceptions by reference
Thirdly: Prefer to have your exception object fall in the inheritance tree of std::exception.
Lastly: What the hell are you trying to do?
I'm new to C++ (coming from C) and writing a class B that is a member of another class A.
The member B will throw an exception if the parent tries to access data that does not exist from B's container (I throw an invalid_argument exception). The member B has an object that can be thought of like an STL container, so it will be for this example.
My question is: if I catch the original invalid_parameter exception in A, is it considered good C++ practice to re-throw the same exception (I'd re-throw the original error, but I do some logging in it, so the what() is different), or can I just throw std::exception. My code now has many
try { A.calls_b_exception } catch (std::invalid_argument& ie) {...} catch (std::exception& e) {...}
blocks and I was wondering if I could reduce them to
try { A.calls_b_exception } catch (std::exception& e) {...}
and still be following good C++ paradigms.
Example code that is similar to my situation:
class B
{
std::vector<int> stuff;
int get_value(int index)
{
if (index >= stuff.size()) {
stringstream err;
err << "--> invalid index " << index << " for stuff";
throw std::invalid_argument(err.str());
}
}
}
class A
{
B b;
// Assume there are methods to add a bunch of stuff to B
int get_value(int index)
{
try {
b.get_value();
} catch (std::invalid_argument& ie) {
stringstream err;
err << ie.what() << "\n\t--> A::get_value(" << index << ")";
// should I throw the same exception here or is this considered good C++ etiquette?
throw std::exception(err.str());
} catch (std::exception& e) {
throw; // something I was not anticipating handling happened
}
}
}
int main
{
A a;
// Assume more stuff to add to A
try {
a.get_value(-1);
}
catch (std::exception& e) {
stringstream err;
err << "--> invalid index " << index << " for main";
throw std::exception(err.str());exception here?
}
}
You cannot instantiate std::exception(std::string), so my initial approach will not work.
Thanks to those of you who took time to read through my question and help me out.
I have many different exceptions defined in exception.thrift:
exception InvalidArgumentsError {
1: string parameter
}
/**
* Server has an problem while executing a function.
* Execution aborted.
*/
exception ServerInternalError {
1: string parameter
}
/**
* Server answer is empty.
*/
exception NoDataError {
1: string parameter
}
This is how i catch them in my C++ code:
catch (InvalidArgumentsError & ex) {
std::cout << ex.parameter;
}
catch (ServerInternalError & ex) {
std::cout << ex.parameter;
}
catch (NoDataError & ex) {
std::cout << ex.parameter;
}
catch (apache::thrift::TException& ex) {
std::cout << "TException:\n" << ex.what();
} catch (const std::exception& ex) {
std::cout << ex.what();
return;
}
I want to write something like this and catch all my exceptions:
catch (SomeBasicException& ex) {
std::cout << ex.what();
}
catch (const std::exception& ex) {
std::cout << ex.what();
}
If I just catch TException and call what() I just get 'Default TException' message because derived classed do not override virtual what() method.
Generated code by thrift compiler:
class InvalidArgumentsError : public ::apache::thrift::TException {
public:
static const char* ascii_fingerprint; //..
static const uint8_t binary_fingerprint[16]; //..
InvalidArgumentsError() : parameter() {
}
virtual ~InvalidArgumentsError() throw() {}
std::string parameter;
_InvalidArgumentsError__isset __isset;
void __set_parameter(const std::string& val) {
parameter = val;
}
//...
};
If you want to stop the repetitive typing then this might be a solution.
When you want to catch your exceptions, you write something like this:
catch (...) {
handle_exception(print_message);
}
print_message is a function that does whatever you want with the message (in this case, print it):
void print_message(char const* const msg)
{
std::cout << msg;
}
handle_exception is written like this:
template<typename F>
void handle_exception(F handler)
try {
throw;
}
catch (InvalidArgumentsError const& ex) {
handler(ex.parameter.c_str());
}
catch (ServerInternalError const& ex) {
handler(ex.parameter.c_str());
}
catch (NoDataError const& ex) {
handler(ex.parameter.c_str());
}
catch (apache::thrift::TException const& ex) {
handler(ex.what());
}
catch (std::exception const& ex) {
handler(ex.what());
}
To handle a new exception you add it to the catch clauses of the handle_exception function.
Albeit this does not really answer the question literally (#Simple did a good job at this already) I would like to propose a somewhat different approach.
Given the code posted above:
exception InvalidArgumentsError {
1: string parameter
}
exception ServerInternalError {
1: string parameter
}
exception NoDataError {
1: string parameter
}
If we look at the pattern, we could - without loosing any information and without producing greater incompatibilities - change it into this:
enum ErrorCode
Success = 0, // always good to have some null value
ServerInternalError = 1
NoData = 2
InvalidArguments = 3
// add more errors here
}
exception MyServiceException {
1: string parameter
2: ErrorCode code
}
I'm fully aware that this might not fit your particular problem (e.g. if there are more exception data than just a 1:parameter). But there may be cases where that approach could be worth considering. I've used it myself quite a few times.
This is the code I have.
try
{
// code throws potentially unknown exception
}
catch (...)
{
std::exception_ptr eptr = std::current_exception();
// then what ?
}
Ideally, I would like to get the string associated to the exception if it is a std::exception.
// then what ?
here is what:
#include <exception>
#include <stdexcept>
#include <iostream>
#include <string>
std::string what(const std::exception_ptr &eptr = std::current_exception())
{
if (!eptr) { throw std::bad_exception(); }
try { std::rethrow_exception(eptr); }
catch (const std::exception &e) { return e.what() ; }
catch (const std::string &e) { return e ; }
catch (const char *e) { return e ; }
catch (...) { return "who knows"; }
}
int main()
{
try { throw std::runtime_error("it's success!"); }
catch (...) { std::cerr << "Here is WHAT happened: " << what() << std::endl; }
try { throw 42; } catch (...) { std::cerr << "and now what: " << what() << std::endl; }
}
what it prints:
Here is WHAT happened: it's success!
and now what: who knows
http://coliru.stacked-crooked.com/a/1851d2ab9faa3a24
so this allows to get what in the catch-all clause.
but what if exception is nested??? here is what:
std::string what(const std::exception_ptr &eptr = std::current_exception());
template <typename T>
std::string nested_what(const T &e)
{
try { std::rethrow_if_nested(e); }
catch (...) { return " (" + what(std::current_exception()) + ")"; }
return {};
}
std::string what(const std::exception_ptr &eptr)
{
if (!eptr) { throw std::bad_exception(); }
try { std::rethrow_exception(eptr); }
catch (const std::exception &e) { return e.what() + nested_what(e); }
catch (const std::string &e) { return e ; }
catch (const char *e) { return e ; }
catch (...) { return "who knows"; }
}
using example from here:
#include <fstream>
...
// sample function that catches an exception and wraps it in a nested exception
void open_file(const std::string& s)
{
try {
std::ifstream file(s);
file.exceptions(std::ios_base::failbit);
} catch(...) {
std::throw_with_nested( std::runtime_error("Couldn't open " + s) );
}
}
// sample function that catches an exception and wraps it in a nested exception
void run()
{
try {
open_file("nonexistent.file");
} catch(...) {
std::throw_with_nested( std::runtime_error("run() failed") );
}
}
int main()
{
try { throw std::runtime_error("success!"); }
catch (...) { std::cerr << "Here is WHAT happened: \"" << what() << '\"' << std::endl; }
try { run(); }
catch (...) { std::cerr << "what happened for run: \"" << what() << '\"' << std::endl; }
}
what is printed:
Here is WHAT happened: "success!"
what happened for run: "run() failed (Couldn't open nonexistent.file (basic_ios::clear))"
http://coliru.stacked-crooked.com/a/901a0c19297f02b5
but what if recursion too deep? what if stackoverflow? optimized what:
#include <typeinfo>
template <typename T>
std::exception_ptr get_nested(const T &e)
{
try
{
auto &nested = dynamic_cast<const std::nested_exception&>(e);
return nested.nested_ptr();
}
catch (const std::bad_cast &)
{ return nullptr; }
}
#if 0 // alternative get_nested
std::exception_ptr get_nested()
{
try { throw ; }
catch (const std::nested_exception &e) { return e.nested_ptr(); }
catch (...) { return nullptr ; }
}
#endif
std::string what(std::exception_ptr eptr = std::current_exception())
{
if (!eptr) { throw std::bad_exception(); }
std::string whaaat;
std::size_t num_nested = 0;
next:
{
try
{
std::exception_ptr yeptr;
std::swap(eptr, yeptr);
std::rethrow_exception(yeptr);
}
catch (const std::exception &e) { whaaat += e.what() ; eptr = get_nested(e); }
catch (const std::string &e) { whaaat += e ; }
catch (const char *e) { whaaat += e ; }
catch (...) { whaaat += "who knows"; }
if (eptr) { whaaat += " ("; num_nested++; goto next; }
}
whaaat += std::string(num_nested, ')');
return whaaat;
}
the same whats:
Here is WHAT happened: "success!"
here is what: "run() failed (Couldn't open nonexistent.file (basic_ios::clear))"
http://coliru.stacked-crooked.com/a/32ec5af5b1d43453
UPD
The similar functionality can be implemented in C++03 by using a trick that allows to rethrow current exception outside of catch block: https://stackoverflow.com/a/3641809/5447906
try
{
std::rethrow_exception(eptr);
}
catch (const std::exception& e)
{
std::cerr << e.what() << std::endl;
}
http://en.cppreference.com/w/cpp/error/exception_ptr
Using std::current_exception seems a bit over the top in your case, since you don't seem to want to store or copy the std::exception_ptr for later processing (which is its only intent, it doesn't help with gaining additional information about an unknown exception in any way). If you just want to treat the case of a std::exception, what about the simple:
try
{
// code throws potentially unknown exception
}
catch (const std::exception &e)
{
std::cerr << e.what() << '\n'; // or whatever
}
catch (...)
{
// well ok, still unknown what to do now,
// but a std::exception_ptr doesn't help the situation either.
std::cerr << "unknown exception\n";
}
Not the best solution in my opinion but seems to work.
try
{
// code throws potentially unknown exception
}
catch (const std::exception& e)
{
std::cerr << e.what() << std::endl;
}
catch (...)
{
std::exception_ptr eptr = std::current_exception();
// then what ?
LogUnknownException();
}
Thanks to ForEveR for the initial solution but I am not sure if I want to throw again within the catch block.
I have defined a simple int error code:
#define my_error 20
Somewhere in my code I throw this error:
throw my_error;
Now I want to try and catch this exception thrown:
try
{
...
...
}
catch (my_error)
{
cout << "Error: my error";
}
Unfortunately the compiler doesn't approve this:
syntax error : 'constant'
catch handlers must specify one type
'try' block starting on line '34' has no catch handlers
Is there a way to do this?
20 is not a type, so you can't catch it. What you can do is filter the values in the catch block:
catch (int exception)
{
if ( exception == 20 )
cout << "Error: my error";
}
An even better approach would be to define your own exception:
class MyException : public std::exception
{
}
//...
try
{
throw MyException();
}
catch(MyException& ex)
{
}
If you use C++11, you can use decltype(my_error), just in case you ever change the type of my_error.
try {
// ...
} catch (const decltype(my_error)& e) {
// ...
}
Here is a demo.