0

我在网上遇到了一个练习,这是文字:

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

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

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

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

~ int_stack ( ) 析构函数,

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

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

void operator < (int p) 将 p 值压入(添加)堆栈,

int operator >(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;
}

我究竟做错了什么?

4

4 回答 4

1

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

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

两个析构函数都会删除构造函数分配的数组s0

于 2013-10-30T18:45:29.757 回答
1

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

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

重载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
}

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

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

于 2013-10-30T19:09:26.047 回答
0

界面的选择非常糟糕,但忽略这一事实考虑您的成员的意思,特别是p. 索引p是指最后添加的元素上方的位置。当您在pop操作中返回值时,您正在从该位置读取值,但该位置没有值:

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

关于界面, pushoperator<operator>pop操作都是不自然的选择。当有人读入代码s < 5时,他们会解释为您正在s与 5 进行比较,而不是在堆栈中插入元素s。那将是混乱的根源。

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

value = s > 5;

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

于 2013-10-30T18:41:43.387 回答
-1

这是我想出的工作实现。

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

此外,索引工作,界面已从<>运算符更改为两个简单的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;
}
于 2013-10-30T20:57:20.450 回答