Question

I made a basic program for making a stack of integers for an intermediate C++ class. The whole thing compiles fine, but I get 2 problems: the capacity always shows up as 0, and a segfault when I test the overloaded assignment operator (Stack1 = Stack2). I know it is probably because of the same thing, but what should be changed?

#include <iostream>
#include <ostream>
#include <cstring>
#include <stdexcept>

using namespace std;

class Stack
{
    //overloaded "<<" for outputting the stack's contents
    friend ostream& operator<<(ostream& leftOp, const Stack& rightOp);

  public:

    Stack(); //constructor
    Stack(const Stack& s); //copy constructor
    ~Stack(); //destructor
    const Stack& operator=(const Stack& rightOp); //assign one stack to another
    void clear(); //set the stack size back to 0
    bool empty() const; //checks whether or not the stack is empty
    unsigned int size() const; //returns the size
    unsigned int capacity() const; //returns the capacity
    int top() const throw(out_of_range); //returns the top value
    void push(int item); //adds a new value
    void pop() throw(out_of_range); //removes the top value
    void reserve(unsigned int newCapacity); //enlarges the array

  private:

    unsigned int stackCap; //stack capacity
    unsigned int stackSize; //stack size
    int* stackArray; //pointer to the stack, to be dynamically allocated
};

int main()
   {
   cout << "Testing default constructor\n\n";

   Stack s1;

   cout << "s1: " << s1 << endl;   
   cout << "s1 size: " << s1.size() << ", capacity: " << s1.capacity() << endl;
   cout << "s1 is " << ((s1.empty()) ? "empty\n" : "not empty\n");
   cout << endl;

   cout << "Testing push()\n\n";

   for (int i = 10; i < 80; i+= 10)
      s1.push(i);

   cout << "s1: " << s1 << endl;   
   cout << "s1 size: " << s1.size() << ", capacity: " << s1.capacity() << endl;
   cout << "s1 is " << ((s1.empty()) ? "empty\n" : "not empty\n");
   cout << endl;

   for (int i = 15; i < 85; i+= 10)
      s1.push(i);

   cout << "s1: " << s1 << endl;   
   cout << "s1 size: " << s1.size() << ", capacity: " << s1.capacity() << endl;
   cout << "s1 is " << ((s1.empty()) ? "empty\n" : "not empty\n");
   cout << endl;

   cout << "Testing copy constructor()\n\n";

   Stack s2 = s1;

   cout << "s1: " << s1 << endl;   
   cout << "s1 size: " << s1.size() << ", capacity: " << s1.capacity() << endl;
   cout << "s1 is " << ((s1.empty()) ? "empty\n" : "not empty\n");
   cout << endl;   

   cout << "Testing top()\n\n";

   cout << "Top item of s1: " << s1.top() << endl << endl;

   cout << "Testing pop()\n\nTop item of s1: ";

   while (!s1.empty())
      {
      cout << s1.top() << ' ';
      s1.pop();
      }

   cout << endl << endl;
   cout << "s1: " << s1 << endl;   
   cout << "s1 size: " << s1.size() << ", capacity: " << s1.capacity() << endl;
   cout << "s1 is " << ((s1.empty()) ? "empty\n" : "not empty\n");
   cout << endl;

   cout << "Testing assignment operator\n\n";

   Stack s3;

   s3 = s2;

   cout << "s2 (size " << s2.size() << "): " << s2 << endl;
   cout << "s3 (size " << s3.size() << "): " << s3 << endl << endl;

   cout << "Testing clear()\n\n";

   s2.clear();

   cout << "s2: " << s2 << endl;   
   cout << "s2 size: " << s2.size() << ", capacity: " << s2.capacity() << endl;
   cout << "s2 is " << ((s2.empty()) ? "empty\n" : "not empty\n");
   cout << endl;

   cout << "s3: " << s3 << endl;   
   cout << "s3 size: " << s3.size() << ", capacity: " << s3.capacity() << endl;
   cout << "s3 is " << ((s3.empty()) ? "empty\n" : "not empty\n");
   cout << endl;

   cout << "Testing assignment to self and swap\n\n";

   s3 = s3;
   s2 = s3;
   s3.clear();

   cout << "s2 (size " << s2.size() << "): " << s2 << endl;
   cout << "s3 (size " << s3.size() << "): " << s3 << endl << endl;

   cout << "Testing chained assignment\n\n";

   Stack s4;

   s4 = s3 = s2;

   cout << "s2 (size " << s2.size() << "): " << s2 << endl;
   cout << "s3 (size " << s3.size() << "): " << s3 << endl;
   cout << "s4 (size " << s4.size() << "): " << s4 << endl << endl;

   cout << "Testing const correctness\n\n";

   const Stack& r4 = s4;

   cout << "s4: " << r4 << endl;   
   cout << "s4 size: " << r4.size() << ", capacity: " << r4.capacity() << endl;
   cout << "s4 is " << ((r4.empty()) ? "empty\n" : "not empty\n");
   cout << "\nTop item of s4: " << r4.top() << endl << endl;

   s1 = r4;

   cout << "s1: " << s1 << endl;   
   cout << "s1 size: " << s1.size() << ", capacity: " << s1.capacity() << endl;
   cout << "s1 is " << ((s1.empty()) ? "empty\n" : "not empty\n");
   cout << endl;   

   s1.clear();

   cout << "s1: " << s1 << endl;   
   cout << "s1 size: " << s1.size() << ", capacity: " << s1.capacity() << endl;
   cout << "s1 is " << ((s1.empty()) ? "empty\n" : "not empty\n");
   cout << endl;   

   cout << "Testing top() with empty stack\n\n";

   try
      {
      cout << s1.top() << endl;
      }
   catch (out_of_range orex)
      {
      cout << orex.what() << endl << endl;
      }

   cout << "Testing pop() with empty stack\n\n";

   try
      {
      s1.pop();
      }
   catch (out_of_range orex)
      {
      cout << orex.what() << endl;
      }

   return 0;
   }

Stack::Stack()
{
    stackCap = 0;
    stackSize = 0;
    stackArray = '\0';

}

Stack::Stack(const Stack& s)  //copy constructor
{
    stackCap = s.capacity();
    stackSize = s.size();
    if (s.stackCap == 0)
        stackArray = '\0';
    else
    {
        stackArray = new int[stackCap];
        for (unsigned int i=0; i < stackSize; i++) //copy the string except for the nullbyte
        {
            stackArray[i] = s.stackArray[i]; //copy it one character at a time into the main string
        }
    }

}

Stack::~Stack()  //destructor
{
    delete stackArray;
}

const Stack& Stack::operator=(const Stack& rightOp)  //assign one stack to another
{
    if (rightOp.stackArray == '\0')
    {
        stackCap = 0;
        stackSize = 0;
        stackArray = '\0';
    }
    else
    {
        delete[] stackArray; //delete that array that is the wrong size!
        stackSize = rightOp.stackSize;
        stackCap = rightOp.stackCap;
        if (rightOp.capacity() == 0)
            stackArray = '\0';
        else
        {
            stackArray = new int[stackCap];
            for (unsigned int i=0; i < stackSize; i++) //copy the string except for the nullbyte
            {
                stackArray[i] = rightOp.stackArray[i]; //copy it one character at a time into the main string
            }
        }
    }
    return *this;
}

void Stack::clear() 
{
    stackSize = 0;
}

bool Stack::empty() const
{
    return (stackSize == 0);
}

unsigned int Stack::size() const
{
    return stackSize;
}

unsigned int Stack::capacity() const
{
    return stackCap;
}


int Stack::top() const throw(out_of_range)
{
    if ( empty() == true )
        throw out_of_range("top(): stack is empty");
    else
        return stackArray[stackSize];
}

void Stack::push(int item)
{
    if (stackCap == stackSize)
        reserve(stackCap * 2);
    stackArray[stackSize] = item;
    stackSize++;
}

void Stack::pop() throw(out_of_range)
{
    if ( empty() == true )
        throw out_of_range("top(): stack is empty");

    stackSize--;

    if (stackSize > 0 && stackSize == stackCap / 4)
        reserve(stackCap / 2);
}

void Stack::reserve(unsigned int newCapacity)
{
    int* copyArray = new int[newCapacity];

    for (unsigned int i = 0; i < stackSize; i++)
    {
        copyArray[i] = stackArray[i];
    }

    stackCap = newCapacity;
    delete[] stackArray;
    stackArray = copyArray;
}

ostream& operator<<(ostream& leftOp, const Stack& rightOp) //prints out the stacks contents
{
    for (unsigned int i = 0; i < rightOp.stackSize; i++) //run the loop for the number of rightOp elements
        leftOp << rightOp.stackArray[i] << " "; //read the elements into leftOp stream
    return leftOp;
}
Was it helpful?

Solution

Your code didn't handle s3 = s3; well. You referenced s3.stackArray after deleting it.

One way to fix this issue is to add if (this == &rightOp) return *this; in the beginning of operator=().

Also, since your initial capacity is 0, and you always grow it by reserve(stackCap * 2), it always stuck at 0. Either use non-0 initial capacity or specially handle 0.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top