我在网上看到了一个练习,这是文字:
编写一个类int_stack来管理一堆整数。该 整数值将存储在动态分配的数组中。
本课程将提出以下成员函数:
将动态分配n的int_stack(int 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;
}
我做错了什么?
答案 0 :(得分:1)
除了使索引正确之外,该类还需要一个复制构造函数和赋值运算符。如上所述,您将获得同一数据块的多个删除:
int_stack s0;
int_stack s1(s0); // uh-oh
两个析构函数都将删除由s0
。
答案 1 :(得分: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 []
。
答案 2 :(得分:0)
界面的选择非常糟糕,但忽略这一事实会考虑你的成员的意思,特别是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
答案 3 :(得分:-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;
}