C++ how to implement a resizable stack array? - c++

In one of my earlier lab exercises I implemented a simple stack program
#include<iostream>
#include<fstream>
#include<string>
using namespace std;
int count = 0; //stores the indexed number
string myStack[20]; //stores the data from file
string fileName;
fstream readFile;
string storeFile; //stores the data as a string
//function declarations/prototypes
void push(string aString);
string top();
string pop();
bool isEmpty();
int main(int argc, char *argv[])
{
fileName = "file.txt";
readFile.open(fileName); //attempts to read the file
while(readFile >> storeFile){
if(readFile.bad()) {
cerr << "File failed to read " << endl;
break; //loop terminates
} else {
push(storeFile); //pushes file to stack
}
}
readFile.close();
while(isEmpty() !=true) { //while file is not emptpy return the top stack.
cout << top() << endl;
pop();
}
return 0;
}
void push(string value) {
myStack[count] = value;
count++;
}
string pop() {
if(count < 0) {
return NULL;
} else {
count--; //decrement count for stack
return myStack[count]; //return top value
}
}
string top() { //returns the current element at the top of the stack
return myStack[count];
}
bool isEmpty() { //checks whether or not the stack is empty
if(count < 0) {
return true;
}
else return false;
}
I am now required to revisit this program, however, this time modify it so that If you attempt to push data onto a full stack you should create a new array of twice the current size, copy the data from the old stack to the new stack and then delete the old stack without using STL or classes. We are allowed to use dynamic memory
So if the input, for example, looked something like this with an array size of 2
push 1
push 1
push 1
push 1
push 1
pop
pop
push 1
Then the output would look like this
Stack doubled from 2 to 4.
Stack doubled from 4 to 8.
Stack contains 4 entries.
How would I implement this? Thankyou
Push attempt
int dataCount = 0;
const int SIZE = 5;
int capacity = 0;
int myStack[SIZE];
void push(int value)
{
if(SIZE == capacity) {
cout << "Doubling current size " << endl;
capacity = capacity * 2;
int* temp = new int[capacity];
copy_n(myStack, SIZE, temp);
std::swap(myStack, temp);
delete[] temp;
}
myStack[dataCount] = value;
dataCount++;
}

What you are asking for requires the stack array to be allocated in dynamic memory, eg:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int count = 0; //stores the indexed number
int capacity = 0; //stores the allocated size
string *myStack = NULL; //stores the data from file
//function declarations/prototypes
void push(const string &aString);
string top();
void pop();
bool isEmpty();
void cleanup();
int main(int argc, char *argv[])
{
string storeFile; //stores the data as a string
string fileName = "file.txt";
ifstream readFile(fileName); //attempts to read the file
while (readFile >> storeFile) {
push(storeFile); //pushes file to stack
}
if (readFile.bad()) {
cerr << "File failed to read " << endl;
}
readFile.close();
while (!isEmpty()) { //while file is not empty return the top stack.
cout << top() << endl;
pop();
}
cleanup();
return 0;
}
void push(const string &value) {
if (count == capacity) {
int newCapacity = (capacity == 0) ? 20 : (capacity * 2);
string *newStack = new string[newCapacity];
for(int i = 0; i < count; ++i) {
newStack[i] = myStack[i];
}
delete[] myStack;
myStack = newStack;
capacity = newCapacity;
}
myStack[count] = value;
++count;
}
string top() {
if (count <= 0) {
return string();
}
return myStack[count-1]; //return top value
}
void pop() {
if (count > 0) {
--count; //decrement count for stack
myStack[count] = "";
}
}
bool isEmpty() {
return (count < 1);
}
void cleanup() {
capacity = count = 0;
delete[] myStack;
myStack = NULL;
}

Create a class That has
-Array start pointer
-current size
-the current position of the stack pointer
a method that inflate the array , delete the previous one and copy the data of the previous
-have a method that push on the stack and one that pops on top of the stack
You can event handle shrinking the stack when pop is less than length of the stack /2

Related

Values in dynamic array cannot be assigned

I am using a stack to reverse a given string. Each character of the string is pushed onto the stack, then they are popped back into a new string which is returned to main. But for some reason, the value of stack[top] in the stack class code never seems to change.
#include <iostream>
#include <string>
using namespace std;
const int size = 4;
class Stack{
private:
//char stack[size];
char* stack;
int top;
public:
Stack()
{
top = -1;
}
void Init_Size(int size)
{
stack = new char[size];
}
bool isFull()
{
if (top == (size - 1))
return true;
return false;
}
bool isEmpty()
{
if (top == -1)
return true;
return false;
}
void push(char c)
{
if (isFull())
{
cout << "STACK IS FULL" << endl;
return;
}
top++;
stack[top] == c;
cout << "PUSHED" << stack[top] << " ONTO STACK" << endl;
}
char pop()
{
if (isEmpty())
{
cout << "STACK IS EMPTY" << endl;
return '/'; //error
}
char temp = stack[top];
cout << stack[top] << endl;
top--;
cout << "POPPED" << temp << " OFF STACK" << endl;
return temp;
}
};
string ReverseString(string str)
{
Stack stack;
string result;
stack.Init_Size(str.length());
for (int i=0; i < str.length(); i++)
{
stack.push(str[i]);
}
for (int i=0; i < str.length(); i++)
{
result[i] = stack.pop();
}
return result;
}
int main()
{
string str;
cin >> str;
cout << ReverseString(str);
}
I tried using a normal array for the stack instead of a dynamic one, but no change, however, I did notice that the value of the stack array can be changed but only in the void Init_Size(int size) function and I'm not sure why.
I see a number of errors in your program:
size: You have a global constant size set to 4 which is used in your isFull function, independent of the local size parameter used in Init_Size. Make this a class variable instead.
Your push function has the line stack[top] == c with two = instead of one - thus comparing the value against stack instead of setting stack. Turn on warnings and you should have found this yourself
ReverseString assigns directly to result[i] without ever setting the size of result. You could have used the str variable instead, since that is just a copy.
Those three are the major errors that need fixing for your program to work, but there are several minor issues as well, like using namespace std; thereby making size ambigious, making unnecessary copies of strings, using new and c-style arrays etc.
You have a problem with creation and deletion of your arrays here in your program as well as a few small misshaps on the way.
Fix:
#include <iostream>
#include <string>
using namespace std;
class Stack{
private:
//char stack[size];
int size;
char* stack;
public:
Stack() : size(0), stack(NULL) {}
~Stack() {if (stack != NULL) delete stack;} //THIS IS NEEDED HERE
void Init_Size(int newSize)
{
if (stack != NULL) delete stack;
size = newSize;
stack = new char[newSize]; //CREATES DYNAMIC ARRAY WHICH YOU NEED TO REMEMBER TO REMOVE OTHERWISE MEMORY LEAK
}
void push(char c) //adds
{
//adding here should work in a way:
//a) create new dynamic array with different size
//b) copy all elements into new array
//c) delete array
if (stack == NULL) Init_Size(1);
char* newArray = new char[size+1];
for(int i = 0; i < size; i++)
{
newArray[i] = stack[i];
}
newArray[size] = c;
delete stack;
stack = newArray;
size++;
cout << "PUSHED " << stack[size-1] << " ONTO STACK" << endl;
}
char pop()
{
//removing here should work in a way:
//a) create new dynamic array with different size
//b) copy all elements into new array
//c) delete array
if (stack == NULL)
{
cout << "Stack empty" << endl;
return '\0';
}
char* newArray = new char[size-1];
for(int i = 0; i < size-1; i++)
{
newArray[i] = stack[i];
}
char temp = stack[size-1];
delete stack;
stack = newArray;
size--;
cout << "POPPED " << temp << " OFF STACK" << endl;
return temp;
}
};
string ReverseString(string str)
{
Stack stack;
string result;
stack.Init_Size(str.length());
for (int i=0; i < str.length(); i++)
{
stack.push(str[i]);
}
for (int i=0; i < str.length(); i++)
{
result[i] = stack.pop();
}
return result;
}
int main()
{
string str;
cin >> str;
cout << ReverseString(str);
}

Stack implementation using array C++

I am trying to implement some of the methods of the class "stack". For the push() method I am trying to duplicate the capacity of the array if the top of the stack equals the capacity. The top is the item of the next slot. I was doing this by creating a new array with double the capacity of the original array and then copying the content over. All the other methods I implemented (empty(), pop(), top()) seem to be working fine but the push function prints random values for the first 4 items of the stack for some reason if the stack has more than 10 elements (The capacity had to be increased). Why is this problem happening?
#include <iostream>
using namespace std;
class stack
{
public:
stack();
bool empty();
void pop();
void push(int x);
int &topElem();
private:
int *buffer;
int top; // Top element of stack
int capacity = 10; // Capacity of array
};
stack::stack()
{
int *val = new int[capacity];
buffer = val;
top = 0;
}
bool stack::empty()
{
if(top == 0)
return true;
else
return false;
}
void stack::push(int x)
{
if(top == capacity)
{
int *newArray = new int[capacity * 2];
for(int i = 0; i < capacity; i++)
{
newArray[i] = buffer[i];
//cout << "newArray[" << i << "]: " << newArray[i] << endl;
}
buffer = newArray;
delete[] newArray;
newArray = NULL;
}
buffer[top] = x;
top++;
}
void stack::pop()
{
if(!empty())
{
top--;
}
else
cout << "Stack is empty!" << endl;
}
int& stack::topElem()
{
return buffer[top - 1];
}
int main()
{
stack plates;
for (int i = 0; i < 20; i++) // Add 20 elements to the stack
{
plates.push(i);
}
while (!plates.empty())
{
cout << plates.topElem() << endl; // Prints the elemtents of the stack
plates.pop(); // Pops the last element of the stack
}
return 0;
}
// Output
19
18
17
16
15
14
13
12
11
10
9
8
7
6
5
4
393
-1250224288
393
-1250206816
buffer = newArray;
delete[] newArray;
this doesn't do what you expect. It points buffer to the new array, leaking the old one, then deleting the memory the buffer is pointing to.
You probably want something like:
delete[] buffer; // free the old buffer
buffer = newArray; // point it to the newly allocated memory

Checking if a word is a palindrome by reversing a stack without using any prewritten functions

#include <iostream>
#include <string>
using namespace std;
#define Max 100000
class Stack {
private:
int top =-1;
char letters[Max];
public:
void setTop(int t) {
top = t;
}
int getTop() {
return top;
}
bool isEmptyStack() {
if (top == -1) {
return true;
}
else{ return false;
}
}
char push(char x,int s) {
if (top != s - 1){
top++;
x = letters[top];
return x;
}
}
char pop() {
if ((isEmptyStack())==false){
cout << "the deleted value is: " << l[top]<<endl;
top--;
return l[top];
}
}
};
void reverse(char letters[], char temp[], int size, Stack stack) {
int i=0;
for (i = 0; i < size; i++) {
stack.push(letters[i],size);
}
i = 0;
cout << temp<<endl;
while (stack.isEmptyStack() == false)
{
letters[-1] = stack.getTop();
stack.pop();
stack.push(letters[i],size);
i++;
}
/* for (int i = 0; i < size; i++) {
cout << temp[i];
}*/
}
int myStringLength(const char* letter)
{
for (int i = 0, c = 0; letter[i] != '\0'; i++, c++) {
if (letter[i] != '\0')
for (; letter[i] != '\0'; i++, c++)
if (letter[i] == '\0') break;
return c;
}
}
int main()
//initializes the main function
{
Stack stack;
string w;
std::cout << "Enter a Word: ";
getline(cin,w);
char* letters = &w[0];
// sets the character text array to set the number of characters equal to the size of the string
//calls the processData function
std::cout << letters<<endl;
int size = myStringLength(letters);
reverse(letters, letters, size, stack);
return 0;//returns the function at 0.
}
I set out to create a program that will check if a word is a palindrome(meaning it is spelled the same normally and if the word is reversed.) I am not yet at that point that is just the final objective. In my code, I have created a stack class because I wanted to feel the satisfaction of getting the same result using my own code. My problem is the stack is not reversing it is returning some weird characters that I don't have the keys on my keyboard to replicate.
The desired outcome should be word's reversed characters.
if the word is food the function should be returning doof. I have already compared the reversed stack to the original and printed the final statement. I fixed the char letters[];
If you're open to using a simple function instead of a Stack then you could use the following program since it is much more simple than your Stack version and hence less-error prone.
#include <iostream>
#include <string>
bool checkIfPalindroom(const std::string &str)
{
for(int i=0;i<(str.size()/2);i++)
{
if (str[i] != str[str.size() - i - 1])
{
return false;//if this if is satisfied even once, return false
}
}
return true;//if the control flow reaches here this will mean that no if was satisfied and hence return true
}
int main()
{
std::string myString = "Somearbitrarystring";
if(checkIfPalindroom(myString))//call the function
{
std::cout<<"The given string: "<<myString <<" is a palindrome"<<std::endl;
}
else
{
std::cout<<"The given string: "<<myString<<" is not a palindrome"<<std::endl;
}
return 0;
}

C++ Array Based Stack

I am trying to double a stack once it gets full. I have tried calling the copy constructor, and when I call it the stack doesn't keep pushing words.
The code run perfectly before it gets full, but once it gets full is where my problem occur. What am I doing wrong?
#include<iostream>
#include<fstream>
#include<string>
//#include "ArgumentManager.h"
#include "Stack.h"
using namespace std;
int main(int argc, char** argv){
//ArgumentManager am(argc, argv); //Instantiating parser for command line arguments
//ReAdInG tHe InPuT fIlE nAmE
//ifstream infile(am.get("A").c_str()); // file to read from, getting name from command line
//ofstream outfile(am.get("C").c_str()); // output file, getting name from command line
ifstream infile;
ofstream outfile;
arrayStack<string> firstStack(10);
arrayStack<string> secondStack(firstStack);
firstStack.stackInitialize();
infile.open("input.txt");
outfile.open("output.txt");
//iF tHe FiLe IsNt ReAd
if(!infile){
std::cout << "ErRor[Input file not Found] YoU hAd OnE jOb....ShAmE" << endl;
std::cout << "ExItInG PrOgRaM!!! GoOdByE" << endl;
return 0;
};
string tester; // to get the words
//READ FROM INFILE AND OUTPUT TO OUTFILE
while(infile >> tester){
for(int i = 0; i < tester.size(); ++i)
{ // CHECK IF A SPECIAL CHARACTER IS ON THE FILE
if(!((tester[i] >= 'a' && tester[i] <= 'z')||(tester[i] >= 'A' && tester[i]<= 'Z')))
{
tester[i] = '\0';
}
}
firstStack.push(tester);
};
while(!firstStack.stackIsEmpty())
{
string b = firstStack.top();
outfile << b << " ";
cout << b << " ";
if(firstStack.stackIsFull()){
secondStack.push(tester)
};
firstStack.pop();
}
infile.close();
outfile.close();
return 0;
}
Also I have tried to call the copy constructor in the push function such as:
template <class Type>
void arrayStack<Type>::push(const Type& word){
if(topStack != maxStackSize){
list[topStack] = word; // adding a new word to the STACK
topStack++;
}
else
cout << "YOU KNOW YOU CAN'T ADD TO A FULL STACK............SHAME" << endl;
arrayStack<Type> newArrayStack(maxStackSize*2);
for(int i = 0; i < maxStackSize; i++){
newArrayStack.push(list[i]);
}
newArrayStack.push(word);
stackCopy(newArrayStack);
}
It doesn't work either.
Below is the Stack Template
//ARRAY BASED STACK TEMPLATE
#ifndef H_ArrayStack
#define H_ArrayStack
#include <iostream>
using namespace std;
template <class Type>
class arrayStack{
private:
int maxStackSize; // the maximum height of the STACK
int topStack; // the top of the STACK
void stackCopy(const arrayStack<Type>& newArrayStack);
Type *list; // array based needs pointer to hold the stack element
public:
const arrayStack<Type>& operator=(const arrayStack<Type>&);
void stackInitialize(){ topStack = 0;}; //Ensure the array stack is empty
bool stackIsEmpty() const{return(topStack == 0);}; //check if stack is empty, is const so will not be messed with
bool stackIsFull() const{return topStack == maxStackSize;}; // just like line 8 except check if it is full
void push(const Type& word); // add a word to the array STACK
void pop(); //remove a word from the array and increment the top
Type top() const; //returns the top of the STACK
arrayStack(int size); //the default constructor
arrayStack(const arrayStack<Type>& newArrayStack); // the copy constructor which allows a new STACK
~arrayStack(){delete [] list;}; // it is an array so to ensure no memory leaks the stack must be deleted after use
};
template <class Type>
void arrayStack<Type>::push(const Type& word){
if(topStack != maxStackSize){
list[topStack] = word; // adding a new word to the STACK
topStack++;
}
else{
cout << "YOU KNOW YOU CAN'T ADD TO A FULL STACK............SHAME" << endl;
int size = maxStackSize;
maxStackSize *= 2;
Type *temp = new Type[maxStackSize]; // create temp and double the size of list
for(int i = 0; i < size; i++){ // copy over all the values
temp[i] = list[i];
}
delete [] list; // delete the list
list = temp; // point to the resized list
list[topStack] = word;
topStack++;
}
}
template <class Type>
void arrayStack<Type>::pop(){
if (!stackIsEmpty()){
topStack--;
}
}
template <class Type>
Type arrayStack<Type>::top() const{
if(topStack == 0){
return 0;
}
else
return list[topStack - 1];
}
template <class Type>
arrayStack<Type>::arrayStack(int size){
maxStackSize = size;
topStack = 0;
list = new Type[maxStackSize];
}
template <class Type>
void arrayStack<Type>::stackCopy(const arrayStack<Type>& newArrayStack){
maxStackSize = newArrayStack.maxStackSize;
topStack = newArrayStack.topStack;
list = new Type[maxStackSize];
for(int j = 0; j < topStack; j++)
list[j] = newArrayStack.list[j];
}
template <class Type>
arrayStack<Type>::arrayStack(const arrayStack<Type>& newArrayStack){
stackCopy(newArrayStack);
}
template <class Type>
const arrayStack<Type>& arrayStack<Type>::operator=(const arrayStack<Type>& newArrayStack){
if(this != &newArrayStack)
stackCopy(newArrayStack);
return *this;
}
#endif
From:
arrayStack<Type> newArrayStack(maxStackSize*2);
for(int i = 0; i < maxStackSize; i++){
newArrayStack.push(list[i]);
}
newArrayStack.push(word);
stackCopy(newArrayStack);
To:
int size = maxStackSize;
maxStackSize *= 2;
Type *temp = new Type[maxStackSize]; // create temp and double the size of list
for(int i = 0; i < size; i++){ // copy over all the values
temp[i] = list[i];
}
delete [] list; // delete the list
list = temp; // point to the resized list
list[topStack] = word;
topStackk++;
Try this in you push function this will double the size of the stack. Like someone mentioned in the comments you have errors in your copy constructor and stackcopy function

Why is the 98th element in my Stack implementation such a bizarre value?

I have the following stack data structure implementation in C++:
// file: Stack.h
#pragma once
#include <iostream>
#include <exception>
class CStack
{
private:
int counter;
int *data;
int currentmaxsize;
void adjust();
public:
void push(int value);
int pop();
int peek();
int getsize();
CStack();
~CStack();
};
// file: Stack.cpp
#include "Stack.h"
void CStack::adjust()
{
int *temp = new int[currentmaxsize];
for (int i = 0; i < counter; i++)
{
temp[i] = data[i];
}
delete data;
data = new int[currentmaxsize * 2];
for (int i = 0; i < counter; i++)
{
data[i] = temp[i];
}
delete temp;
currentmaxsize *= 2;
}
int CStack::getsize()
{
return counter;
}
void CStack::push(int value)
{
if (counter+1 == currentmaxsize)
{
adjust();
}
counter++;
data[counter] = value;
}
int CStack::peek()
{
return data[counter];
}
int CStack::pop()
{
if (counter > 0)
{
int ret = data[counter];
counter--;
return ret;
}
else if (counter == 0)
{
throw std::exception("cannot pop empty stack");
}
return 0xFFFFFFFF;
}
CStack::CStack()
{
data = new int[100];
currentmaxsize = 100;
counter = 0;
}
CStack::~CStack()
{
delete data;
}
This is a fairly standard stack implementation. The only thing that is different from the kind of stack you would see in most textbooks is the adjust() function, which reallocates the stack with a bigger size if the original boundary is reached.
I wrote the following driver for the data structure as well:
// file: driver.cpp
#include <iostream>
#include "Stack.h"
int main(int argc, char *argv[])
{
CStack stack;
for (int i = 0; i < 200; i++)
{
stack.push(i);
std::cout << "Pushed: " << i << std::endl;
//std::cout << "New stack size: " << stack.getsize() << std::endl;
}
int len = stack.getsize();
std::cout << "len = " << len << std::endl;
for (int i = 0; i < len; i++)
{
std::cout << "Popped: " << stack.pop() << std::endl;
//std::cout << "New stack size: " << stack.getsize() << std::endl;
}
return 0;
}
This works almost as I would expect it to, except this one value in the program output:
Popped: 100
Popped: 99
Popped: 7798895
Popped: 97
Popped: 96
It is always the value of the 98th element in the stack that has a bizarre value like this, and I don't know why it is - the adjust() function is being called when the stack hits 100 values, not 99, so I don't imagine it's a problem with the adjust function.
Your push and peek and probably other functions use counter as the index of the last element. But other parts of your code use counter as the number of elements so counter-1 would be the index of last. So data is lost during adjust
Select one design: The valid indexes are 0 through counter-1 inclusive or 0 though counter or 1 through counter (wasting position 0).
I only like the first of those choices but any one of them can work (your existing code is closest to being the third). Having different parts play by different rules doesn't work.
I see at least one bug. You are using delete after doing a new[].
new should be matched with delete and new[] should be matched with delete[]. Otherwise it's undefined behavior.
Also, you are doing unnecessary copying in your adjust function.