int mult (int a, int b)
{
if (a <= 0 || b <= 0) throw (" Your input is invalid. No zero");
int doub = a * b;
if (doub <= 0) throw (" Invalid value");
cout << "\\n" << doub;
return doub;
}
//code that gives values of num1 & num2//
try
{
mult(num1, num2);
}
catch (int error)
{
cerr << " Error ###$% invalid value";
}
The program works fine if both values (num1, numa2) are higher than 0, but if any value is less than 0 the program fails and doesn't throw the desired message. It just shows a default error.
Is it inproper use of the pre & post condition?
Is it the throw usage? (I have some doubts in how to use it, it might be that but I don't know)
throw (" Your input is invalid. No zero"); You are throwing a char *
catch (int error) But you are catching an int. This is a different type from char * so the exception is not caught and propagates up to the default handler.
The idiomatic way to do handle this would be to throw (std::runtime_error("Your input is invalid. No zero"));,
and catch (std::exception & e) { cerr << e.what(); }
You are throwing exceptions of type const char * but catching them as type int. To fix this, all you need to do is change:
catch (int error)
to:
catch (const char * error)
Live demo
Or, as QuestionC says, you can throw a std::runtime_error and catch that.
Related
I'm following an example code from Programming Principles and Practice Using C++ in one of the example for exception it shows this snippet of code
int main()
{
try {
vector<int> v; // a vector of ints
for (int x; cin >> x; )
v.push_back(x); // set values
for (int i = 0; i <= v.size(); ++i) // print values
cout << "v[" << i << "] == " << v[i] << '\n';
}
catch (const out_of_range& e) {
cerr << "Oops! Range error\n";
return 1;
}
catch (...) { // catch all other exceptions
cerr << "Exception: something went wrong\n";
return 2;
}
}
From what I understand it is suppose to catch out_of_range error and output "Oops! Range error". However, the Visual Studio 2019 shows this instead.
can someone explain why it shows me this
Does “try-catch” catches run time error (especially Out of Range error)?
No, in C++ most run time errors lead to Undefined Behavior, not exceptions. Only errors which explicitly throw exceptions can be caught.
std::vector<T>::operator[] does not specify that it throws an exception when you access out of bounds, it is just Undefined Behavior and anything can happen. It can even appear to work. When I try it here, there isn't any visible error : https://godbolt.org/z/Pcv9Gn8M9
If you want an exception on out of bounds access, std::vector<T>::at() does throw std::out_of_range.
For your test you should use v.at(i) instead of v[i]. Try it here : https://godbolt.org/z/szKxhjxhx.
// The following code works fine, throwing a std::out_of_range exception:
std::vector<double> vd{ 1.5 };
try {
int i{ -1 };
double d = vd.at(i); // exception is thrown
}
catch (std::out_of_range& re) {
std::cout << "Exception is " << re.what() << std::endl; // invalid vector subscript
}
If I access vector elements in a for loop with an invalid index, no std::exception is thrown although I use .at(). Why is the std::out_of_range exception not thrown?
// in a for loop, this does not throw the exception!
std::vector<double> vd{ 1.5 };
try {
for (int i = -1; i < vd.size(); ++i)
double d = vd.at(i); // exception is not thrown. Why?
}
catch (std::out_of_range& re) {
std::cout << "Exception is " << re.what() << std::endl; // exception is not thrown
}
Because the loop does not execute. -1 < vd.size() is false.
size() returns an unsigned value. So before comparing the two numbers -1 is converted into an unsigned value. This conversion is done modulo the largest unsigned value plus one, which means that -1 is converted to the largest possible unsigned value. That is then compared with the size of your vector, and that comparison is always false.
Signed/unsigned comparsions are problematic for this reason. Although well defined, they don't work in the mathematically expected way if the signed value is negative. Your compiler should warn you about this problem.
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.
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;
}
I'm trying to throw an exception in my code if a vector that is created from user input is not sorted in either descending or ascending order.
using namespace std;
#include <iostream>
#include <vector>
#include <algorithm>
int main () {
vector <int> vec;
//Let user fill a vector with 12 integers.
//cout << "Please note that input data should be either increasing or decreasing." << endl;
int n = 0;
int size = 0;
while(size < 12) {
cout << "Type integer to add to the vector." << endl;
cin >> n;
vec.push_back(n);
++size;
}
//throw exception if unsorted
try {
if (!((is_sorted(vec.begin(), vec.end())) || (is_sorted(vec.end(), vec.begin())))) {
throw "Input was not sorted.";
}
}
catch(exception &error){
cerr << "Error: " << error.what() << endl;
}
}
I have not included the rest of the code, which searches for a particular number, because I am pretty sure that it is irrelevant to this issue. When the data filled into the vector is ascending or descending, everything is fine, but when I test the exception, I get, "terminate called after throwing an instance of 'char const*' Aborted" instead of my desired error message. I don't understand what is going on here. Is it something wrong with the way I'm handling exceptions or am I using the sort() function incorrectly?
In C++, all types are throwable and catchable, but you are only catching subclasses of std::exception.
The best fix to your code would be changing your throw statement to:
throw std::runtime_error("Input was not sorted.");
If you want to catch an exception, you should throw an exception, not a const char*.
See this answer: c++ exception : throwing std::string
You're throwing a const char* not an std::exception. So catch it as a const char*:
catch(const char* error) {
std::cout << "Error: " << error << "\n";
}
Or throw an std::exception.
Remember that you can throw many types and have many catch blocks, the one that will be invoked is the one that matches the type of the thrown exception.