Assign value using overloaded subscript operator - c++

I am trying to create custom array indexed from 1 using subscript operator. Getting value works fine, but I have no clue, why assign using subscript operator doesn't work.
class CEntry {
public:
CKey key;
CValue val;
CEntry(const CKey& key, const CValue& val) {
this->key = key;
this->val = val;
}
CEntry& operator= (const CEntry& b) {
*this = b;
return *this;
};
};
...
class EntriesArray {
public:
CEntry **entries;
int length;
EntriesArray(int length) {
this->length = length;
entries = new CEntry*[length];
int i;
for (i = 0; i < length + 1; i++) {
entries[i] = NULL;
}
};
CEntry& operator[] (const int index) {
if (index < 1 || index > length) {
throw ArrayOutOfBounds();
}
return *entries[index - 1];
};
};
Constructs array this way
EntriesArray a(5);
This works
a.entries[0] = new CEntry(CKey(1), CValue(1));
cout << a[1].val.value << endl;
This doesn't work
a[1] = new CEntry(CKey(1), CValue(1));
EDIT:
Using
CEntry *operator=( CEntry *orig)
it compiles okey, but gdb stops at
No memory available to program now: unsafe to call malloc warning: Unable to restore previously selected frame
with backtrace
Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_PROTECTION_FAILURE at address: 0x00007fff5f3ffff8
0x00000001000013c8 in CEntry::operator= (this=0x0, orig=0x1001008d0) at /Users/seal/Desktop/efa du2_pokus2/efa du2_pokus2/main.cpp:20
20 /Users/seal/Desktop/efa du2_pokus2/efa du2_pokus2/main.cpp: No such file or directory.
in /Users/seal/Desktop/efa du2_pokus2/efa du2_pokus2/main.cpp

At first... This:
CEntry& operator= (const CEntry& b) {
*this = b;
return *this;
};
Shouldn't work (this should result in recursive call of operator=).
The second thing is that you're trying to assign CEntry * to CEntry, this would work if you had CEntry *operator=( CEntry *orig), but I think this is bad coding practice.

This question may be related to this one.
I tried to fix your code; I believe that this is what you were trying to do:
(tested this code on g++ 5.3.0)
#include <iostream>
#include <stdexcept>
#include <string>
// Some implementation for CKey and CValue:
typedef int CKey;
struct CValue {
int value;
CValue(int value=0) : value(value) {}
};
class CEntry {
public:
CKey key;
CValue val;
CEntry(): key(0), val(0) {}
CEntry(const CKey& key, const CValue& val): key(key), val(val) {}
CEntry& operator= (const CEntry& b) {
this->key = b.key;
this->val = b.val;
return *this;
};
};
class EntriesArray {
public:
CEntry *entries;
int length;
EntriesArray(int length) {
this->length = length;
entries = new CEntry[length];
};
CEntry& operator[] (const int index) {
if (index < 1 || index > length) {
throw std::domain_error("out of bounds!");
}
return entries[index - 1];
};
};
int main(int argc, char* argv[]) {
using namespace std;
EntriesArray a(5);
// This works
a.entries[0] = CEntry(CKey(1), CValue(1));
cout << a[1].val.value << endl;
// This doesn't work
a[1] = CEntry(CKey(2), CValue(2));
cout << a[1].val.value << endl;
}
Also you might want to use a[1] as a[1].val.value e.g.:
cout << a[1] << endl;
To do this just add to this line to cEntry:
operator int() { return val.value; }
I hope it helps.

You could try replacing
CEntry& operator[] (const int index) {
if (index < 1 || index > length) {
throw ArrayOutOfBounds();
}
return *entries[index - 1];
};
with
void Add(const int index, CEntry *pEntry) {
if (index < 1 || index > length) {
throw ArrayOutOfBounds();
}
entries[index - 1] = pEntry;
};
but since you are now storing references to objects allocated on the heap (with new) you will need a destructor ~EntriesArray() to delete them all.

Because EntriesArray::operator[] returns a CEntry &, but new CEntry returns a CEntry *.
Perhaps you want a[1] = CEntry(CKey(1), CValue(1))? (no new.)
By the way, your current definition of CEntry::operator= will lead to a stack overflow.

This
return *entries[index - 1];
dereferences a NULL pointer.
You want the pointer itself to be overwritten by a[1] = new CEntry(CKey(1), CValue(1));, not the pointed-to-value.
Try this:
class EntriesArray
{
public:
int length;
CEntry **entries;
EntriesArray( int length ) : length(length), entries(new CEntry*[length]())
{
}
// defaulted special member functions are inappropriate for this class
EntriesArray( const EntriesArray& ); // need custom copy-constructor
~EntriesArray(); // need custom destructor
EntriesArray& operator=(const EntriesArray&); // need custom assignment-operator
CEntry*& operator[] (const int index) {
if (index < 1 || index > length) {
throw ArrayOutOfBounds();
}
return entries[index - 1];
}
};

Further to my comment above:
To make it work with writing new values, you probably need something like this
(I haven't double checked for off by one or ptr vs reference stuff)
CEntry& operator[] (const int index) {
if (index < 1) {
throw ArrayOutOfBounds();
}
// Add default elements between the current end of the list and the
// non existent entry we just selected.
//
for(int i = length; i < index; i++)
{
// BUG is here.
// We don't actually know how "entries" was allocated, so we can't
// assume we can just add to it.
// We'd need to try to resize entries before coming into this loop.
// (anyone remember realloc()? ;-)
entries[i] = new CEntry();
}
return *entries[index - 1];
};

Related

overload operator [] to give a specific index from array of objects

I have class XOBoard that present an array that is size n*n,each cell of the array is an Object called Cell.
Each Cell object is defined by
class Cell {
private:
char ch;
public:
Cell(char ch = '.');
char getCellValue();
void setCellValue(char nch);
};
Board is defined this way:
class XOBoard {
private:
int n;
Cell **Board;
};
XOBoard::XOBoard(int n) { //constructor
this->n = (n >= 3) ? n : 3;
Board = new Cell*[n];
for (int i = 0; i < n; i++) {
Board[i] = new Cell[n];
}
}
I wanted to get to a specific Cell value by using this method: board1[{1,2}], but I want to check if the values that sent to me is withing the range(n), but unfortantly I was unable to get to the Board array, and to n variable.
Here is the code:
XOBoard& operator[](list<int> list){
int x = list.front(), y = list.back();
return Board[x][y].getCellValue();
}
Thanks a head!
As mentioned in the comments, using operator[] for multidimensional subscripting is unconventional, but if you want that, you should make sure you get the correct amount of values (2 in this case) and that you return the correct type (a Cell& in this case).
Also be aware of shadowing. If you try to construct a Board with a value less than 3, you'll set this->n to 3 but go on with the construction using the erroneous n (that may even be a negative value).
More comments inline:
#include <iostream>
#include <stdexcept>
#include <tuple>
class Cell {
private:
char ch;
public:
Cell(char nch = '.') : // after the colon comes the member initializer list
ch(nch) // which is usually good to use
{
// if(ch is not valid) throw ...
}
char getCellValue() const { return ch; }
// a convenient conversion operator to automatically
// convert a Cell to a char where a char is needed
// (like when streaming a Cell to std::cout)
operator char() const { return ch; }
// void setCellValue(char nch); // replaced by operator=
Cell& operator=(char nch) {
// if(nch is not valid) throw ...
ch = nch;
return *this;
}
};
class XOBoard {
private:
size_t n; // use an unsigned type for sizes/indices
Cell** Board;
public:
// constructor
XOBoard(size_t xy_size) : // a member initializer list again
n(xy_size >= 3 ? xy_size : 3), // assign to "n" here
Board(new Cell*[n]) // the correct n is now used
{
// if the below construction fails, a bad_alloc will be thrown.
// you need to add code to clean up what you've already allocated to take
// care of that situation.
for(size_t i = 0; i < n; i++) {
Board[i] = new Cell[n];
}
}
// Copying or moving need careful handling of the pointers.
// Read "The rule of three/five/zero". Until then, disable it.
XOBoard(const XOBoard&) = delete;
XOBoard& operator=(const XOBoard&) = delete;
// destructor
~XOBoard() {
for(size_t i = 0; i < n; i++) delete[] Board[i];
delete[] Board;
}
// added for convenience
size_t size() const { return n; }
// return a Cell& and use a std::pair since you
// expect exactly 2 values
Cell& operator[](std::pair<size_t, size_t> pos) {
auto& [x, y] = pos;
if(x>=n || y>=n)
throw std::out_of_range("{"+std::to_string(x)+","+std::to_string(y)+"}");
return Board[x][y];
}
};
int main() {
try {
XOBoard a{2}; // trying an invalid size
std::cout << a.size() << '\n';
a[{2, 2}] = 'a';
std::cout << a[{2, 2}] << '\n';
Cell x = 'b';
a[{2, 2}] = x;
std::cout << a[{2, 2}] << '\n';
a[{2, 3}] = 'c'; // index out of bounds
} catch(const std::out_of_range& ex) {
std::cerr << "out_of_range exception: " << ex.what() << '\n';
}
}
Output:
3
a
b
out_of_range exception: {2,3}
You should try to avoid raw pointers and actual multidimensional arrays. It's often better to emulate dimensionality by allocating a 1d array and provide an interface to the user that calculates the correct element to work on.

too many parameters for this operator function

First, I'm not good at english and also first time in StackOverflow, but I try to explain about my code's problem.
I was asked to make my own Vector(similar thing) from my professer, and there's a problem in fuction which returns a reference to the element at the requested position in the vector container. If the requested position is out of range, it should output some messages and terminate the program.
I should make this to Operator overloading, and this is my code.
double operator [](int n, const MyDoubleVector& _mV)//The arror come out at this line.
{
if(n > num)//'num' is private reference in class to count array. it typed int.
{
return 0;
}
return &_mV.data[n];//'data' is private reference in class. It declare like 'double *data = new double [num];'
}
I saw that sometimes 'friend' solve this, but when I put 'friend' in this line, it said me like "operator[] must be a member function."
Finally, Ihave no idea how to do. Would you please help me?
You need to implement the overload of operator[] as a member function of your class MyDoubleVector.
Here's the definition :
double & MyDoubleVector::operator[](int index);
operator [] must be defined as a member of the class.
example:
#include <iostream>
#include <cstdlib>
#include <algorithm>
struct MyDoubleVector
{
MyDoubleVector()
{}
MyDoubleVector(MyDoubleVector const& other)
{
// very naiive copy constructor
if (other.data)
{
std::for_each(other.data, other.data + other.num, [&](double val)
{
this->push(val);
});
}
}
MyDoubleVector& operator=(MyDoubleVector const& other)
{
auto temp = other; // invoke copy constructor
std::swap(num, temp.num);
std::swap(capacity, temp.capacity);
std::swap(data, temp.data);
return *this;
}
~MyDoubleVector()
{
delete [] data;
}
double& operator [](int n);
/** either define the method inline like this...
{
if(n > num)
{
std::cerr << "MyDoubleVector::operator[]: index " << n << " out of range" << std::endl;
std::exit(100);
}
return data[n];
}
**/
void push(double val)
{
if (num == capacity)
{
more();
}
data[num++] = val;
}
private:
void more()
{
if (!data)
{
data = new double [10];
capacity = 16;
}
else
{
auto newcapacity = capacity * 2;
auto newdata = new double [newcapacity];
std::copy(data, data + capacity, newdata);
std::swap(data, newdata);
capacity = newcapacity;
delete [] newdata;
}
}
int num = 0;
int capacity = 0;
double* data = nullptr;
};
/** ...
** or out of line like this
**/
double& MyDoubleVector::operator [](int n)
{
if(n > num)
{
std::cerr << "MyDoubleVector::operator[]: index " << n << " out of range" << std::endl;
std::exit(100);
}
return data[n];
}
int main()
{
MyDoubleVector v;
v.push(10.0);
v[1];
}

Writing an accessor method for inherited class with sparse member data?

Say I have a simple vector class, vec:
#include <iostream>
#include <stdlib.h>
class vec {
public:
vec() {}
// Constructor.
vec(int n) {
len = n;
data = new double[len];
}
// Destructor.
~vec() { delete [] data; }
// Accessor.
double & operator[](int i) const {
check_index(i);
return data[i];
}
// Other methods...
// ....
protected:
int len;
double * data;
void check_index(int i) const {
if(i < 0 || i >= len) {
std::cerr << "Bad access.\n";
exit(1);
}
}
};
Now suppose I have a special type of vector with sparse structure, e.g., where every even-index is zero. Call this oddvec. Instances of oddvec should be declared just as with the vec class, but underneath, the memory use should be efficient since only half the data is non-zero.
The accessor for the oddvec class should return 0 if the index is even, and return the odd-index element (stored sequentially) otherwise. There a couple problems with this:
The double & return type is violated if the index is even, since the constant value, 0, is returned.
It's not clear to me how to handle the situation when an even index element is used as an lvalue. E.g., v[0] = 3.0 should not be allowed in the oddvec class, but is perfectly acceptable in the vector class. We can't simply throw an error when even indexes are used, because even indexes are fine as long as the intention is as an rvalue.
How do I design the accessor function for the oddvec class, while both keeping the memory storage efficient and inheriting all the methods from the parent?
Non-working example of oddvec:
class oddvec : public vec {
public:
// Constructor.
oddvec(int n) {
len = n;
data = new double[len/2];
}
// Accessor (doesn't work!)
double & operator[](int i) const {
check_index(i);
if (i%2 == 0)
return 0;
else
return data[(i-1)/2];
}
};
Upon compilation:
main.cpp: In member function ‘double& oddvec::operator[](int) const’:
main.cpp:49:20: error: invalid initialization of non-const reference of type ‘double&’ from an rvalue of type ‘double’
return 0;
Working example using proxy classes:
I have implemented a proxy class as suggested in the answer below.
proxies.h
#ifndef PROXIES_H
#define PROXIES_H
#include <iostream>
#include <stdlib.h>
class proxy {
public:
proxy(int i, double v, double * d) {
index = i;
value = v;
data = d;
}
void operator=(double rhs) {
data[index] = rhs;
}
friend std::ostream & operator<<(std::ostream & outs, const proxy & p) {
outs << p.value;
return outs;
}
protected:
int index;
double value;
double * data;
};
class oddproxy : public proxy {
public:
oddproxy(int i, int v, double * d) : proxy(i, v, d) {}
void operator=(double rhs) {
if (index%2 == 0) {
std::cerr << "Even entries of oddvec are not assignable.\n";
exit(1);
}
data[index/2] = rhs;
}
};
#endif
vectors.h
#ifndef VECTORS_H
#define VECTORS_H
#include "proxies.h"
class vec {
public:
vec() {}
// Constructor.
vec(int n) {
len = n;
data = new double[len];
}
// Destructor.
~vec() { delete [] data; }
// Accessor.
proxy operator[](int i) const {
check_index(i);
return proxy(i, data[i], data);
}
inline int length() const { return len; }
// Other methods...
// ....
protected:
int len;
double * data;
void check_index(int i) const {
if(i < 0 || i >= len) {
std::cerr << "Bad access.\n";
exit(1);
}
}
};
class oddvec : public vec {
public:
// Constructor.
oddvec(int n) {
len = n;
data = new double[len/2];
}
// Accessor.
oddproxy operator[](int i) const {
check_index(i);
return oddproxy(i, (i%2 == 0) ? 0 : data[i/2], data);
}
};
#endif
main.cpp
#include <iostream>
#include "vectors.h"
int main () {
int N = 5;
vec V(N);
oddvec O(N);
for(int i=0; i < V.length(); i++) {
V[i] = i;
if(i%2 != 0) {
O[i] = i;
}
}
for(int i=0; i < O.length(); i++) {
std::cout << "V[" << i << "]=" << V[i] << ", "
<< "O[" << i << "]=" << O[i] << "\n";
}
O[0] = 13;
return 0;
}
output
V[0]=0, O[0]=0
V[1]=1, O[1]=1
V[2]=2, O[2]=0
V[3]=3, O[3]=3
V[4]=4, O[4]=0
Even entries of oddvec are not assignable.
You can use proxy object to do this.
simple sample code:
#include <iostream>
#include <vector>
using namespace std;
class very_odd_vector{
public:
class only_odd_proxy;
friend class only_odd_proxy;
only_odd_proxy operator [](int index);
int operator [](int index)const{return index%2==0?0:content[index/2];}
unsigned int size()const{return content.size()*2;}
private:
vector<int> content{1,3,5,7,9};
};
class very_odd_vector::only_odd_proxy{
public:
only_odd_proxy(very_odd_vector& vec,int index):vec(vec),index(index){}
operator int(){return index%2==0 ? 0 : vec.content[index/2];}
only_odd_proxy& operator =(int value){
if(index%2==0)
cout << "BAD OPERATION";//any error you want
else
vec.content[index/2] = value;
return *this;
}
private:
very_odd_vector& vec;
int index;
};
auto very_odd_vector::operator [](int index)->only_odd_proxy{return only_odd_proxy(*this,index);}
int main(){
very_odd_vector v;
cout << "reading value\n";
for(int i=0;i<v.size();++i)
cout << v[i] <<'\n';
cout << "writting value\n";
for(int i=0;i<v.size();++i){
cout << i << ':';
v[i]=10;
cout << '\n';
}
cout << "reading value\n";
for(int i=0;i<v.size();++i)
cout << v[i] <<'\n';
}
Edit for updated part of question :
I think this class will fit your need more.
//Both base and inherit class return this class
class maybe_readonly_proxy {
public:
maybe_readonly_proxy(double* data, bool readonly):readonly(readonly),data(data){}
maybe_readonly_proxy& operator=(double rhs) {
if(readonly){/*whatever error*/}
else {*data = rhs;}
return *this;
}
operator double()const{return *data;}
private:
bool readonly;
double * data;
};
You may need a variable to contain readonly (0 in this case) value, or modify the operator double() the check readonly state
Or just implement get and set method separately and do not use this proxy may be another choice.

strange segfault using template as parameter

I have a sorted list, which takes a Comparator as parameter. In a unit test I tried to use two different comparators.
The strange thing is, using the StringReverseComparator with the two if-statements disabled (commented out), all works well and valgrind does not claim any error.
template<typename T> class Comparator {
public:
virtual int compare(const T * left, const T * right) = 0;
};
class StringReverseComparator : public Comparator<String> {
public:
int compare(const String *left, const String *right) {
int rv = strcasecmp((const char *)*left, (const char *)*right);
if (rv < 0) return 10;
if (rv > 0) return -10;
return rv;
}
};
class StringComparator : public Comparator<String> {
public:
int compare(const String *left, const String *right) {
return strcasecmp(left->operator const char*(), right->operator const char*());
}
};
As soon as I enable both if-statements, I get a segfault from sort method.
Sort method is the standard qsort by sedgewick.
const char * is an operator from String class to access the character array.
First I thought, that changing the comparator might cause troubles, so I created a new instance of sorted list. But that traps too as soon as I have the two if-statements enabled.
So what's wrong with the compare method?
//edit:
Ok, first the sort code (taken from sedgewick):
template<typename T> class SortedList {
public:
// rest omitted
protected:
void sort() { qsort(0, _size - 1); }
void qsort(int left, int right) {
if (right > left) {
const T *v = _elements[right], *tmp;
int i = left-1;
int j = right;
for (;;) {
while (_comparator->compare(_elements[++i], v) < 0) ;
while (_comparator->compare(_elements[--j], v) > 0) ;
if (i >= j) break;
tmp = _elements[i];
_elements[i] = _elements[j];
_elements[j] = tmp;
}
tmp = _elements[i];
_elements[i] = _elements[right];
_elements[right] = tmp;
qsort(left, i-1);
qsort(i+1, right);
}
}
private:
int _size;
const T **_elements;
Comparator<T> *_comparator;
};
... and here the operator char *.
by the way: String class passed all unit tests and was ok with valgrind too.
class String {
public:
// rest omitted
operator const char * () const { return _s; }
const char * operator * () const { return _s; }
private:
char *_s;
};
about usage of strcasecmp: my first attempt was:
return strcasecmp( ... ) * (-1);
using the same parameters as in StringComparator. When that failed, I tried anything I could imagine about, including the if-statements and different call syntax of operator char *.
strcasecmp does not return just -1, 0, 1 - as mentioned in many tutorials. The return value differs in size and sign and after -1, 0, 1 failed to, I tried using 10. The value has no significance, could be 815 or 42, what ever.
// edith 2
Thanks you all for your attention!
I solved it myself. The point is, the qsort algo was not safe enuf :(
The following sort code works fine (with any kind of comparator):
void qsort(int left, int right) {
if (right > left) {
const T *v = _elements[right], *tmp;
int i = left-1;
int j = right;
for (;;) {
while (++i < _size && _comparator->compare(_elements[i], v) < 0) ;
while (--j > 0 && _comparator->compare(_elements[j], v) > 0) ;
if (i >= j) break;
tmp = _elements[i];
_elements[i] = _elements[j];
_elements[j] = tmp;
}
tmp = _elements[i];
_elements[i] = _elements[right];
_elements[right] = tmp;
qsort(left, i-1);
qsort(i+1, right);
}
}
Thanks.

Implementing a int stack in C++

I came across a exercise on the web, this is the text:
Write a class int_stack that will manage a stack of integers. The
integers values will be stored in a dynamically allocated array.
This class will propose the following member functions :
int_stack (int n) constructor that will dynamically allocate n
integers,
int_stack ( ) constructor allocating 20 integers,
~ int_stack ( ) destructor,
int empty ( ) the return value is 1 if the stack is empty, 0
otherwise,
int full ( ) the return value is 1 if the stack is full, 0 otherwise,
void operator < (int p) pushes (add) the p value on the stack,
int operator >(int p) returns (and remove) the value on the top of
the stack
I've tried to implement it, but the > (pull) operator won't work.
Here's my code:
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;
}
What am I doing wrong?
In addition to getting the indexing right, the class needs a copy constructor and an assignment operator. As written you'll get multiple deletes of the same data block:
int_stack s0;
int_stack s1(s0); // uh-oh
Both destructors will delete the array allocated by the constructor for s0.
There are several major flaws with you code:
Unless you want to resize the stack every time you push or pop something onto or off of it, respectively, you probably want to use a linked-list- or deque- style storage structure instead of a vector/array-style.
Overloading operator< and operator> to do what amounts to extraction and insertion is a terrible interface choice. I would urge against using operators for those operations:
void int_stack::push(int i)
{
// push an element onto the stack
}
int int_stack::pop()
{
// pop an element off of the stack
}
Because you are not implementing it as a linked-list or deque, when you go to push elements, you can (and eventually will) attempt to write outside the bounds of the memory you allocated.
Finally, you do not delete your stack properly. If you use new [], you must also use delete [].
The choice of interface is quite bad, but ignoring that fact consider what your members mean, in particular p. The index p refers to the location above the last added element. When you return the value in the pop operation you are reading the value from that location, but that location does not have a value:
int int_stack::operator >(int i)
{
if(!this->empty())
return this->stack[p--]; // <-- predecrement!
return 0;
}
Regarding the interface, operator< and operator> are unnatural choices for the push and pop operations. When someone reads in code s < 5 they interpret that you are comparing s with 5, not inserting an element into the stack s. That is going to be the source of confusion.
Worse than operator< is operator> defined as int operator>(int). User code to read a value will end up looking as:
value = s > 5;
That looks like comparing s to 5, and storing the result into value. Moreover, the actual behavior is completely independent on the argument 5, the same operation can be spelled as s > -1 or even s > 5.3
Here is the working implementation I came up with.
It implements a copy constructor and the assignment operator.
Also, the indexing works, and the interface has changed from the < and > operators to two simple push(int) and int pop() functions.
It throws exceptions when you try to push/pop over the boundaries.
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;
}