Help with Exception Handling

Hello fellow member! I am an Intermediate C++ Programmer, and while studying Exception Handling, I encountered two problems.

Firstly, how does the compiler know which catch() body to use if the there are multiple catch() with the same argument.

Secondly, to practice the new concepts I learned, I tried building a simple calculator. However, I have encountered errors on the statement:

for(int i=0; i<strlen(number1); i++)
                if( (!isdigit(number1[i])) && (number1[i] != "."))
                      throw number1;

for(int j=0; j<strlen(number2); j++)
                if( (!isdigit(number2[j])) && (number2[j] != "."))
                      throw number2;



The error says that "ISO C++ forbids comparison between pointer and integer."

Here is my full code:

#include<iostream>
#include<string>
using namespace std;
int main()
{
    double operand1, operand2, result;
    char number1[50];
    char number2[50];
    char oper;
    
    try{
        cout<<"Please enter a number, operator, and a number:\n";
        cin>>number1>>oper>>number2;
        
        for(int i=0; i<strlen(number1); i++)
                if( (!isdigit(number1[i])) && (number1[i] != "."))
                      throw number1;
        
        operand1 = atof(number1);
        
        for(int j=0; j<strlen(number2); j++)
                if( (!isdigit(number2[j])) && (number2[j] != "."))
                      throw number2;
        
        operand2 = atof(number2);
              
        if(oper != '+' && oper != '-' && oper != '*' && oper != '/')
                throw oper;
        
        if(oper == '/')
                if(operand2 == 0)
                      throw operand2;
                      
        switch (oper)
        {
               case '+':
                    result = operand1 + operand2;
                    break;
               
               case '-':
                    result = operand1 - operand2;
                    break;
               
               case '*':
                    result = operand1 * operand2;
                    break;
                    
               case '/':
                    result = operand1 / operand2;
                    break;
                    
                    }
        cout<<"Answer:\t"<<result<<endl<<endl;
        }
        catch(const double* n)
        {
                    cout<<"Division by "<<n<<" not allowed!\n\n";
        }
        catch(const char op)
        {
                    cout<<op<<" is not a valid operator!";
        }
        catch(const char* num)
        {
                    cout<<num<<" is not a valid number!";
        }                      
        catch(...)
        {
        }
        
        system("pause");
        return 0;
}



Thank you very much for the help! It is greatly appreciated and help me clear my doubts on the topic.

Neil010
Last edited on
closed account (zb0S216C)
Neil010 wrote:
"Firstly, how does the compiler know which catch() body to use if the there are multiple catch() with the same argument."

That would be ambiguous. Which one would it use? For a compiler to decide which handler to use, the handler must differ from the other handlers. The compiler will evaluate the type that was thrown, and will determine which handler best fits the thrown type.

Neil010 wrote:
 
(number1[i] != ".")

Of what type is number1? I'm assuming and integral value, since double-quoted strings are pointers.

Wazzak
Last edited on
The compiler will evaluate the type that was thrown, and will determine which handler best fits the thrown type.


What I mean is what happens if the same type is thrown for different exceptions?

For example:

1
2
if(age<0)
    throw "Age must be positive!"


AND

1
2
if(number<100)
    throw "Number must be less than 100!"


were part of a code and throw the same type. They would also both have their own specific handlers, for example (respectively):

1
2
3
4
5
6
7
8
9
10
catch(const char* err)
{
    cout<<err;
}


catch(const char* err2)
{
    cout<<err2;
}



So in this how would the compiler know which handler to use?


And, I was able to find the error in my code, thanks to you. I was comparing a character with a pointer. Hence, when I used single quotes instead of double quotes, my code worked fine.

Thanks once again!

Neil010
I would expect it uses the first innermost catch block that it encounters. So in the case you gave, if you throw a const char* it will always be caught by the err block, and the err2 will never be used.
I would expect it uses the first innermost catch block that it encounters. So in the case you gave, if you throw a const char* it will always be caught by the err block, and the err2 will never be used.


That is exactly what I mean. Is there any other way in which you could use the other handler?
No. Exceptions are only thrown/caught by type. If you need to have the same exception do multiple things then you might be using it wrong. Either that or you need to package the info into the exception itself.
firedraco, I don't quite understand what you mean by (maybe due to lack of knowledge or experience):

If you need to have the same exception do multiple things then you might be using it wrong. Either that or you need to package the info into the exception itself.


What I am trying to say is that, how does the compiler choose the handler that is specific to the exception, if there is another exception that throws the same type?

When you throw exceptions, you aren't throwing a new "type" of exception.

Ex:

1
2
3
4
5
if(num < 0) {
   throw NumberOutOfRange("Number too small");
} else if(num > 100) {
   throw NumberOutOfRange("Number too large");
}


Here you would throw the same exception type (number out of range), but you would give extra information that could be displayed or used if needed.
That is exactly what I mean. Is there any other way in which you could use the other handler?

You could examine the contents of the exception in the innermost catch-clause, and if it isn't what the catch clause expects, rethrow (that is, use throw; with no arguments).

It's pretty common to use the same type exception (e.g. std::runtime_error or std::system_error) to signal different error conditions, the catch-clauses can sort it out.

PS: a couple simple rules to avoid common errors and maintenance headaches
1. throw by value, catch by (const) reference
2. only throw objects derived (directly or indirectly) from std::exception
Last edited on
Thanks for the tips!
Topic archived. No new replies allowed.