How do I prevent the C++ try-catch exception processing from shutting down the program after catch? (I'm a beginner.)

Asked 2 years ago, Updated 2 years ago, 26 views

Outputs a statement that an exception occurred in cout << B.top() << endl; in the code below. After that, the line cout << B.size() << endl; is not executed. If you change the order of these two sentences, it works well, but the sentences after the top are not printed at this time. I think the program ends right after the exception process, but what should I do to make the program work even after the exception process?

void main() {

    try {
        ArrayStack<int> A;
        A.push(7);
        A.push(13);
        cout << A.top() << endl;
        A.push(9);
        cout << A.top() << endl;
        cout << A.top() << endl;
        ArrayStack<string> B(10);
        B.push("Bob");
        B.push("Alice");
        cout << B.top() << endl;
        B.push("Eve");
        A.pop();
        A.pop();
        B.pop();
        B.pop();
        B.pop();
        cout << B.top() << endl;
        cout << B.size() << endl;
    }
    catch (StackEmpty& obj) {
        cout << obj.getMessage() << endl;
    }
    catch (StackFull& obj) {
        cout << obj.getMessage() << endl;
    }
}

c++

2022-09-22 15:15

3 Answers

First of all, you do not need to attach throw specialization to a function as in voidArrayStack<E>:pop()throw()StackEmpty. See the Exception Specification (throw)(C++) document.

template <typename E>
const E& ArrayStack<E>::top() const throw(StackEmpty) {
    try {
        if (isEmpty()) throw StackEmpty("Stack is empty!");
        return S[t];
    }
    catch (StackEmpty& obj) {
        cout << obj.getMessage() << endl;
        If exit(1); // exit(1) is not present, an error occurs during execution.
        // Why does an error occur? How do I return?
    }
    // It is not recommended to include this exception processing inside the function that will cause the exception.
    // It is correct to have the side using this function handle the exception.
}
template <typename E>
const E& ArrayStack<E>::top() const
{
    if (!isEmpty())
        return S[t];

    throw StackEmpty("Stack is empty!");
    // When an exception is thrown, the return value cannot be returned.
    // This is because the side calling this function moves to the catch statement without receiving the return value.
    // But if there is no appropriate catch statement, there will be a problem, right?
}

There is a good example, so please refer to it. Throw exception and return result from a function

I think we can handle it like this in the calling part.

void main()
{
    ArrayStack<int> A;
    ArrayStack<string> B(10);
    try {
        A.push(7);
        A.push(13);
        cout << A.top() << endl;
        A.push(9);
        cout << A.top() << endl;
        cout << A.top() << endl;
        B.push("Bob");
        B.push("Alice");
        cout << B.top() << endl;
        B.push("Eve");
        A.pop();
        A.pop();
        B.pop();
        B.pop();
        B.pop();
        cout << B.top() << endl;
    }
    catch (const RuntimeException& e) {
        cout << e.getMessage() << endl;
    }
    cout << B.size() << endl;
}

+ Answers to additional questions.

template <typename E>
const E& ArrayStack<E>::top() const
{
    if (isEmpty())
        throw StackEmpty("Stack is empty!");

    return S[t];
}

template <typename E>
void ArrayStack<E>::push(const E& e)
{
    if (size() >= capacity)
        throw StackFull("Stack is full!");

    S[++t] = e;
}

template <typename E>
void ArrayStack<E>::pop()
{
    if (isEmpty())
        throw StackEmpty("Stack is empty!");

    t--;
}


2022-09-22 15:15

In the first place, if an exception occurs in the internal code, the purpose of the try statement is not to execute the remaining codes within the range of the try. This is because the exception is likely to prevent the remaining code from working properly.

When you want to safely execute a code that may cause a problem, wrap the block of code with a try and write a code that solves the problem or leaves a log in the catch to prepare for a problem.

Therefore, if an exception occurs within a try, the remaining codes within that try are skipped and moved to a catch statement that can handle the exception that occurred. After the catch statement is executed, the codes after the corresponding try-catch statement are executed again normally again.

In other words, as you worried, the program will not end after catch.

void main() {

    try {
        ArrayStack<int> A;
        A.push(7);
        A.push(13);
        cout << A.top() << endl;
        A.push(9);
        cout << A.top() << endl;
        cout << A.top() << endl;
        ArrayStack<string> B(10);
        B.push("Bob");
        B.push("Alice");
        cout << B.top() << endl;
        B.push("Eve");
        A.pop();
        A.pop();
        B.pop();
        B.pop();
        B.pop();
        cout << B.top() << endl; // Exception (because the stack was empty and I tried to read the internal value)
        cout << B.size() << endl; // Skipped (because exception occurred above)
    }
    catch (StackEmpty&obj) { // catch the exception that occurred
        cout << obj.getMessage() << endl; // Processing
    }
    catch(StackFull&obj) { // This exception did not occur, so skip
        cout << obj.getMessage() << endl;
    }
    // The codes below here are executed normally

}

By the way, if there is no catch statement that can handle the exception that occurred, the problem is different.

Once the code after the try-catch statement is not executed, and if it was a try-catch statement in the main function like the code above, the program will terminate abnormally.

However, it was a try-catch statement within a function, and if there is a catch statement outside that function that can catch the exception, it will go to that catch statement.

void SomeFunction()
{
    // // do something... (4)
    try {
        // // do something... (5)
        // Exception (6)
        // // do something... (x)
    }
    // No catch to receive this exception.
    // // do something... (x)
}

int main()
{
    // // do something... (1)
    try {
        // // do something... (2)
        SomeFunction(); // (3)
        // // do something... (x)
    }
    catch (...) {
        // // do something... (7)
    }
    // // do something... (8)
    return 0;
}

Please refer to the MSDN documentation for more information. (If you read it carefully, it's not difficult.)


2022-09-22 15:15

Oh, and I have another question!

#include <iostream>
#include <string>
using namespace std;

class RuntimeException {
private:
    string errMsg;
public:
    RuntimeException(const string& err) : errMsg(err) {
    }
    string getMessage() const { 
        return errMsg; 
    }
};

class StackEmpty : public RuntimeException {
public:
    StackEmpty(const string& err) : RuntimeException(err) {
    }
};

class StackFull : public RuntimeException {
public:
    StackFull(const string& err) : RuntimeException(err) {
    }
};

template <typename E>
class ArrayStack {
private:
    E* S;          
    int capacity;
    int t; 
public:
    ArrayStack(int cap = 100);
    ~ArrayStack();
    int size() const;
    bool isEmpty() const;
    const E& top() const throw(StackEmpty);
    void push(const E& e) throw(StackFull);
    void pop() throw(StackEmpty);
};

template <typename E>
ArrayStack<E>::ArrayStack(int cap) {
    capacity = cap;
    t = -1;
    S = new E[cap];
}

template <typename E>
ArrayStack<E>::~ArrayStack() {
    delete[] S;
}

template <typename E>
int ArrayStack<E>::size() const {
    return t + 1;
}

template <typename E>
bool ArrayStack<E>::isEmpty() const {
    return (t == -1);
}

template <typename E>
const E& ArrayStack<E>::top() const throw(StackEmpty) {
    try {
        if (isEmpty()) throw StackEmpty("Stack is empty!");
        return S[t];
    }
    catch (StackEmpty& obj) {
        cout << obj.getMessage() << endl;
        If exit(1); // exit(1) is not present, an error occurs during execution.
    }
}

template <typename E>
void ArrayStack<E>::push(const E& e) throw(StackFull) {
    try {
        if (size() == capacity) throw StackFull("Stack is full!");
        S[++t] = e;
    }
    catch (StackFull& obj) {
        cout << obj.getMessage() << endl;
        If exit(1); // exit(1) is not present, an error occurs during execution.
    }
}

template <typename E>
void ArrayStack<E>::pop() throw(StackEmpty) {
    try {
        if (isEmpty()) throw StackEmpty("Stack is empty!");
        t--;
    }
    catch (StackEmpty& obj) {
        cout << obj.getMessage() << endl;
        If exit(1); // exit(1) is not present, an error occurs during execution.
    }
}

void main() {
        ArrayStack<int> A;
        A.push(7);
        A.push(13);
        cout << A.top() << endl;
        A.push(9);
        cout << A.top() << endl;
        cout << A.top() << endl;
        ArrayStack<string> B(10);
        B.push("Bob");
        B.push("Alice");
        cout << B.top() << endl;
        B.push("Eve");
        A.pop();
        A.pop();
        B.pop();
        B.pop();
        B.pop();
        cout << B.top() << endl;
        cout << B.size() << endl;
}



2022-09-22 15:15

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.