在 C++ 中实现 int 堆栈

Implementing a int stack in C++

本文关键字:int 堆栈 实现 C++      更新时间:2023-10-16

我在网上看到了一个练习,这是文本:

编写一个将管理整数堆栈的类int_stack。这 整数值将存储在动态分配的数组中。

此类将提出以下成员函数:

int_stack (int n) 构造函数,将动态分配 n 整数

int_stack ( ) 构造函数分配 20 个整数,

~ int_stack ( ) 析构函数,

int 空 ( ) 如果堆栈为空,则返回值为 1,0 否则

int full ( ) 如果堆栈已满,则返回值为 1,否则返回值为 0,

void 运算符 <(int p) 在堆栈上推送(添加)p 值,

int 运算符>(int p) 返回(并删除)顶部的值 堆栈

我尝试实现它,但>(拉)运算符不起作用。

这是我的代码:

int_stack.h

class int_stack
{
private:
    int* stack;
    unsigned int n, p;
    void init(unsigned int n);
public:
    int_stack(unsigned int n);
    int_stack();
    ~int_stack();
    int empty();
    int full();
    void operator <(int i);
    int operator >(int i);
};

int_stack.cpp

#include "int_stack.h"
void int_stack::init(unsigned int n)
{
    this->stack = new int[n];
    this->p = 0;
}
int_stack::int_stack(unsigned int n)
{
    this->init(n);
}
int_stack::int_stack()
{
    this->init(20);
}
int_stack::~int_stack()
{
    delete this->stack;
}

int int_stack::empty()
{
    return (this->p == 0 ? 1 : 0);
}
int int_stack::full()
{
    return (this->p == n-1 ? 1 : 0);
}
void int_stack::operator <(int i)
{
    if (!this->full())
        this->stack[p++] = i;
}
int int_stack::operator >(int i)
{
    if(!this->empty())
        return this->stack[p--];
    return 0;
}

我做错了什么?

除了正确索引之外,该类还需要一个复制构造函数和一个赋值运算符。如前所述,您将获得同一数据块的多次删除:

int_stack s0;
int_stack s1(s0); // uh-oh

两个析构函数都将删除构造函数为 s0 分配的数组。

您的代码有几个主要缺陷:

除非您想在每次将某些内容推送或弹出到堆栈上或从堆栈上弹出时分别调整堆栈的大小,否则您可能希望使用链接列表或双端样式的存储结构,而不是矢量/数组样式。

重载operator<operator>来执行相当于提取和插入的操作是一个糟糕的界面选择。 我敦促不要在这些操作中使用运算符:

void int_stack::push(int i)
{
    // push an element onto the stack
}
int int_stack::pop()
{
    // pop an element off of the stack
}

因为您没有将其实现为链表或 deque,所以当您去推送元素时,您可以(并且最终会)尝试在分配的内存范围之外写入。

最后,您没有正确删除堆栈。 如果使用new [],则还必须使用delete []

界面的选择非常糟糕,但忽略这一事实请考虑您的成员的含义,尤其是p。索引p是指上次添加的元素上方的位置。在pop操作中返回值时,您正在从该位置读取值,但该位置没有值:

int int_stack::operator >(int i)
{
    if(!this->empty())
        return this->stack[p--];   // <-- predecrement!
    return 0;
}

关于接口,operator<operator>是推送和弹出操作的不自然选择。当有人读取代码时s < 5他们会解释您正在将s与 5 进行比较,而不是将元素插入堆栈s。这将成为混乱的根源。

operator<更糟糕的是operator>定义为int operator>(int)。读取值的用户代码最终将如下所示:

value = s > 5;

这看起来像是将s与 5 进行比较,并将结果存储到 value 中。而且,实际行为完全独立于参数 5,相同的操作可以拼写为 s > -1 甚至s > 5.3

这是我想出的工作实现。

它实现复制构造函数和赋值运算符。

此外,索引工作,界面已从<>运算符更改为两个简单的push(int)int pop()功能。

当您尝试推/弹出边界时,它会引发异常。

int_stack.h

#include <exception>
class int_stack
{
private:
    int* stack;
    unsigned int n, p;
    void init(unsigned int n);
    void copy(int_stack& other);
public:
    int_stack(unsigned int n);
    int_stack();
    int_stack(int_stack& other);
    int_stack& operator=(int_stack& other);
    ~int_stack();
    int empty();
    int full();
    void push(int i);
    int pop();
    class OutOfBoundariesException: public std::exception {};
};

int_stack.cpp

#include "int_stack.h"
void int_stack::init(unsigned int _n)
{
    n = _n;
    stack = new int[n];
    p = 0;
}
int_stack::int_stack(unsigned int n)
{
    init(n);
}
int_stack::int_stack()
{
    init(20);
}
int_stack::int_stack(int_stack& other)
{
    copy(other);
}
int_stack& int_stack::operator=(int_stack& other)
{
    copy(other);
    return *this;
}
void int_stack::copy(int_stack& other)
{
    n = other.n;
    p = other.p;
    stack = new int[n];
    for (unsigned int i = 0; i < n; i++)
        stack[i] = other.stack[i];
}
int_stack::~int_stack()
{
    delete[] stack;
}
int int_stack::empty()
{
    return (p == 0 ? 1 : 0);
}
int int_stack::full()
{
    return (p == n ? 1 : 0);
}
void int_stack::push(int i)
{
    if (!full())
        stack[(++p)-1] = i;
    else
        throw new OutOfBoundariesException;
}
int int_stack::pop()
{
    if (!empty())
        return stack[(p--)-1];
    else
        throw new OutOfBoundariesException;
    return 0;
}