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
Related
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);
}
I'm learning Data Structures as required of me by my university. I've implemented the Queue DS using Dynamic Array but it somehow doesn't work. It updates the value on the first enqueue method call but from the second call onward, it does nothing.
MY CODE
#include <iostream>
#define MAXSIZE 8
class Queue
{
private:
int *arr;
int front;
int rear;
int itemsCount;
public:
Queue()
{
arr = new int[MAXSIZE];
front = -1;
rear = -1;
itemsCount = 0;
}
~Queue()
{
delete[] arr;
}
int dequeue()
{
int x = arr[front];
front = (front + 1) % MAXSIZE;
itemsCount--;
return x;
}
void enqueue(int x)
{
if (empty())
{
front++;
}
rear = (rear + 1) % MAXSIZE;
arr[rear] = x;
itemsCount++;
}
bool full() const
{
if (itemsCount == MAXSIZE)
return true;
return false;
}
bool empty() const
{
if (itemsCount == 0)
return true;
return false;
}
};
int main(int argc, char const *argv[])
{
Queue myQ;
myQ.enqueue(11);
myQ.enqueue(22); // This doesn't update the array at 1th index
myQ.enqueue(33);
myQ.enqueue(44);
myQ.enqueue(55);
myQ.enqueue(66);
myQ.enqueue(77);
myQ.enqueue(88);
std::cout << myQ.dequeue() << std::endl;
return 0;
}
P.S I know the implementation is incomplete and I haven't handled all the edge cases yet. That's because I couldn't get the normal case to work.
P.P.S It works with Static Array. But not with Dynamically allocated one.
Apparently, the array was being updated and the program was running as it should have when I performed the dequeue operations and displayed the values on screen. But the debugger somehow was only showing the value at the first index of the dynamically allocated array.
array pointer
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
So I am trying to create a stack with a dynamic size, meaning that the capacity of the stack will change dynamically as needed. The concept worked out flawlessly in my head, create a function name memoryManagement(int i) that takes the size of data currently stored in the stack by a variable called usedCapacity. After this, the program was supposed to create a new array, use memcpy to copy the contents of the old array onto the new one. And finally, copy the contents of the new array back onto the old one with a new capacity. However, I keep getting a runtime error when I run my program. Also, depending in where I call the showStack function I sometimes get thrash numbers instead of the actual values I pushed onto the stack. If anyone could point me out on what I am doing wrong, I would greatly appreciate it.
#include <iostream>
#include <string>
#include <cstdlib>
#include <cstring>
using namespace std;
class Stack
{
public:
//stack functions
Stack();
void push(int a);
int pop();
int peek() const;
void showStack();
~Stack();
//memory management
void memoryManagement(int a);
//void setCapacity(int );
//void ensureCapacity(int minCapacity);
private:
int top;
int * arr;
int capacity;
int usedCapacity;
};
//////////////////////////////////////////////////////////////////////////////////
int main() {
Stack calc;
calc.push(11);
calc.push(33);
calc.showStack();
calc.push(23);
calc.push(43);
return 0;
}
//////////////////////////////////////////////////////////////////////////////////
Stack::Stack()
{
top = -1;
usedCapacity = 0;
capacity = 1;
arr = new int[capacity];
}
void Stack::push(int a)
{
if (top > capacity)
throw "Stack overflow";
top++;
usedCapacity++;
arr[top] = a;
memoryManagement(usedCapacity);
}
int Stack::pop()
{
if (top <= -1)
throw "Stack underflow";
arr[--top];
}
int Stack::peek() const
{
return top;
}
void Stack::showStack()
{
for (int i = 0; i < capacity; i++)
{
cout << arr[i] << " ";
}
cout << endl;
}
Stack::~Stack()
{
delete[] arr;
}
void Stack::memoryManagement(int a)
{
if (a >= capacity)
{
int newCapacity;
newCapacity = (a * 3) / 2 + 1;
int * arr2 = new int[newCapacity];
memcpy(arr2, arr, sizeof(int) * usedCapacity);
delete[] arr;
arr = arr2;
delete[] arr2;
}
}
Why are you deleting arr2 from memoryManagement? You should not, as that's apparently your new class attribute (you did arr = arr2):
But that's not enough (your program will then start throwing exception upon push....because you also forgot to modify your capacity attribute. Here is your working memoryManagement function:
void Stack::memoryManagement(int a)
{
if (a >= capacity)
{
int newCapacity;
newCapacity = (a * 3) / 2 + 1;
int * arr2 = new int[newCapacity];
memcpy(arr2, arr, sizeof(int) * usedCapacity);
delete[] arr;
arr = arr2;
capacity = newCapacity; // Don't forget that!
//delete[] arr2; // Don't do that!
}
}
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.