在堆栈中执行 POP 时在下溢中进行异常处理

Exception Handling in underflow while doing POP in Stack

本文关键字:异常处理 下溢 POP 堆栈 执行      更新时间:2023-10-16

我想知道如何在顶部变量达到值 -1(没有元素可以弹出)时应用异常处理。目前,我正在使用 cout 来了解用户关于堆栈下溢并返回 0,这不是一个好的做法。这个弹出函数总体上可以做出哪些改进,以及如何在堆栈达到下溢状态时通知用户并处理异常。

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;
}

主要部分 :

case 4:
            std::cout << "POP the element" << std::endl;
            s1.pop();
            break;

您可以抛出out_of_range异常:

#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--];
}

在客户端:

void foo() 
{
   Mystack ms;
   //...
  try 
  {
    ms.pop();
  }
  catch (const std::out_of_range& oor) 
  {
    std::cerr << "Out of Range error: " << oor.what() << 'n';
  }
}

编辑:正如下面的评论所提到的,您还可以从std::exception中得出自己的例外。 下面是一个简单的示例:

#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--];
}

实时(虚拟)示例:http://ideone.com/ZyqiQ0

re

" 这个pop功能的整体改进是什么

您可以

  • 使其void,使其对其他项目类型更加异常安全
    使用当前设计,如果复制弹出的项目失败,则无法恢复。
  • 删除内部输出。
  • assert不会发生下溢,以便可以在测试中捕获此问题。

因此

void Mystack::pop()
{
    assert( top > 0 );
    --top;
}

哇,多么简化 - 现在也更加异常安全!

作为assert的替代方法,您可以引发异常。这比原版好,但绝对不比assert好。它将正确性问题移动到运行时域中,由每个调用方站点处理并可能解决。

使用C++异常的好处是错误处理代码可以与用户代码分开,从而减轻了代码中充斥着 C 程序中常见的错误处理代码的需要。引发异常还提供了在错误情况下返回无效值的解决方案

if( s1.pop() == 0 ){
    // is this an error or not?
}

可以像这样将异常添加到代码中,方法是利用

#include <stdexcept> 

头文件。

int Mystack::pop()
{
    if (isEmpty())
    {
        throw std::range_error("nothing to pop");
    }
    std::cout << "The popped element is" << A[top];
    return A[top--];
}

然后,您将 try/catch 块添加到适当的代码中,也许使用

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;

另一种解决方案,特别适用于错误不是异常的情况,例如文件 I/O 对用户代码的干扰更大,但提供了比返回任意值更好的解决方案

int Mystack::pop(int& value)
{
    if( isEmpty() )
    {
        return 1;
    }
    std::cout << "The popped element is" << A[top];
    value = A[top--];
    return 0
}

然后你的代码就变成了

case 4:
    std::cout << "POP the element" << std::endl;
    {
        int value;
        if( s1.pop(value) == 1 ){
            // error code
        }
    }
        break;