Stack using array - c++

I'm new to coding and was just learning stack and the code below is not giving any output. Can you guys please help me out with what I'm doing wrong in this?
#include<iostream>
using namespace std;
struct stack
{
int size;
int top;
int *arr;
};
int isEmpty(struct stack *ptr)
{
if(ptr->top==-1)
{
return 1;
}
return 0;
}
int isFull(struct stack *ptr)
{
if(ptr->top==ptr->size-1)
{
return 1;
}
return 0;
}
int main()
{
struct stack *s;
s->size = 80;
s->top=-1;
s->arr= new int(80);
if(isEmpty(s))
{
cout<<"the stack is empty"<<endl;
}
else
{
cout<<"the stack is not empty"<<endl;
}
}

Your main bug is that you haven't initialized s to point to anything. You set s->arr using new, but haven't done so for s itself. You dereference s when setting the size, top, etc, and also when checking top. This is undefined behavior.
You need:
struct stack *s = new struct stack;
to fix this.
Also, always remember to check the allocated pointer(s) are not nullptr before proceeding.
You also don't de-allocate the memory (using delete), so you have a memory leak.
Also, you can use instead the defined true and false, instead of 1 and 0, and change the return types to be bool.
Here is a corrected version of your code with the mentioned changes:
#include <iostream>
struct stack {
int size;
int top;
int *arr;
};
bool isEmpty(struct stack *ptr) {
if (ptr->top == -1) {
return true;
}
return false;
}
bool isFull(struct stack *ptr) {
if (ptr->top == ptr->size - 1) {
return true;
}
return false;
}
int main(void) {
/* you have to initialize s to point to something */
struct stack *s = new struct stack;
/* check for nullptr */
if (s == nullptr) {
return EXIT_FAILURE;
}
s->size = 80;
s->top = -1;
/* array of 80 integers */
s->arr = new int[s->size];
/* check for nullptr */
if (s->arr == nullptr) {
return 1;
}
if (isEmpty(s)) {
std::cout << "the stack is empty\n";
} else {
std::cout << "the stack is not empty\n";
}
/* remember to de-allocate the memory -- in the reverse order */
delete[] s->arr;
delete s;
return 0;
}
Tip: always compile your code with some basic compilation flags to check for this sort of thing. For example, you might compile using at least:
g++ -Wall -Werror -Wextra program.cpp
Also, consider using valgrind, which is a powerful tool for detecting memory leaks and uninitialized memory accesses.
A few extra notes:
The code reads like a C program more or less, as pointed out in the comments, so consider whether you want to instead write it as a C program, or adapt it more to C++
You could also instead declare s to be on the stack instead (struct stack s;), access its fields in main like s.size, s.top, etc and then pass s in by its address (&s).

I have commented out where some changes were to be made...
#include<iostream>
using namespace std;
struct stack
{
int size;
int top;
int* arr;
};
int isEmpty(struct stack* ptr)
{
if (ptr->top == -1)
{
return 1;
}
return 0;
}
int isFull(struct stack* ptr)
{
if (ptr->top == ptr->size - 1)
{
return 1;
}
return 0;
}
int main()
{
// s should point to something for initializing top to -1;
struct stack* s = new struct stack;
s->size = 80;
s->arr = new int(80);
// Top is initialized to -1 otherwise the output will be shown as The stack is not empty.
s->top = -1;
if (isEmpty(s))
{
cout << "the stack is empty" << endl;
}
else
{
cout << "the stack is not empty" << endl;
}
}

Related

why does my dynamically allocated array implementation of queue data structure NOT update on the second call?

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

Stack overflow exception for large data sets

I tried solving this problem: http://projecteuler.net/problem=201 But the program below breaks for larger SET size(>20) throwing a stack overflow exception. Is there a memory leak happening? Could you please point out where? Also if the following implementation involves bad coding practice, please let me know. I'm trying to improve my amateur programming skills. Thanks in advance.
EDIT: I edited the code below. I don't get any stack overflow exceptions now. But could anyone suggest me a better algorithm? Thanks!
#include "stdafx.h"
#include <iostream>
#include <cmath>
#include <winsock2.h>
#define SET 100
#define SUBSET 50
class node
{
public:
int data;
node* next;
};
using namespace std;
int sum(int A[SUBSET]);
void combCalc(int S[SET]);
bool search(node* head, int sum);
void appendIfUnique(int total, bool nullHeader);
int _tmain(int argc, _TCHAR* argv[])
{
cout << "Hello World" << endl;
int S [SET];
for(int i=1; i<=SET; i++)
{
S[i-1]= (int)pow((float)i,2);
}
combCalc(S);
cin.get();
return 0;
}
static node *head;
static node *current = head;
void combCalc(int S[])
{
int row=0, col=0;
int elePos[SUBSET], B[SUBSET];
bool nullHeader = true;
for(int z=0; z<SUBSET; z++) // initializing elePos
{
elePos[z]=z;
}
bool notDone = true;
while (notDone || col <(SUBSET-1))
{B[col] = S[elePos[col]];
if(col==(SUBSET-1)) //finished forming a subset
{
notDone = false;
for(int q=(SUBSET-1); q>=0; q--) //incrementing from the last element
{
if(elePos[q]<(SET-SUBSET+q)) //checking if the element has reached its maximum
{
notDone = true;
elePos[q]++;
for(int w=q+1; w<SUBSET; w++) //setting the trailing elements to its minimum
{
elePos[w]=elePos[q]+w-q;
}
break;
}
}
if(notDone){col=0;row++;}
int total = sum(B);
appendIfUnique(total,nullHeader);
nullHeader = false;
}
else
{
col++;
}
}
int result = 0;
for(node *pnode = head; pnode != current->next; pnode=pnode->next)
result = result + pnode->data;
cout << result << endl;
}
int sum(int A[])
{
int total = 0;
for(int i=0; i<SUBSET; i++)
{
total = total + A[i];
}
return total;
}
bool search(node* head, int sum)
{
bool exists = false;
node* pNode = head;
while(pNode != NULL)
{
if(pNode->data == sum)
{
exists = true;
break;
}
pNode = pNode->next;
}
return exists;
}
void appendIfUnique(int total, bool nullHeader)
{
if(nullHeader){head = NULL;}
if(!search(head,total))
{
node *temp;
/*temp=(node *) malloc(sizeof(node));*/
temp = new node();
temp->data = total;
temp->next = NULL;
if(head == NULL)
{
head = current = temp;
}
else
{
current->next = temp;
current = temp;
}
}
}
Some notes:
Break point (in my system: cygwin g++) is SET=18 (17 works)
Problem is due to too much recursion [run it within a debugger] You have too many calls to combCalc(S) (in my case, it dies after 32K calls).
As it has been indicated in the comments, you should probably reconsider your algorithm. In the meantime, a simple modification is to remove the recursion (since it is not even a proper recursion):
int _tmain(int argc, _TCHAR* argv[])
{
cout << "Hello World" << endl;
int S [SET];
for(int i=1; i<=SET; i++)
{
S[i-1]= (int)pow((float)i,2);
}
while(combCalc(S)) { } // <--- keep calling while combCalc is true
cin.get();
return 0;
}
by making combCal() return a bool:
bool combCalc(int S[]) // <--- MODIFY (check also the forward declaration)
{
...
if(notDone || col <(SUBSET-1))
{
...
return true; // <--- MODIFY return true... I need to keep calculating.
}
else
{
int result = 0;
for(node *pnode = head; pnode != current->next; pnode=pnode->next)
result = result + pnode->data;
cout << result << endl;
return false; // <--- MODIFY return false.... we're done
}
}
The above is just a minimum modification. I'm not even sure it solves the problem correctly since I haven't really looked at the algorithm.
You should consider:
Use a less brute force algorithm
Move the while loop within the combCalc()... so you will be having a single call... and in this case you probably can remove the static variables and make them simple local variables.
Consider not using #define for constants.
Consider using STL structures... instead of your own home grown ones. This will remove some of the concerns below.
Consider not using malloc but using new (more C++)
You're not using free this means that the memory you allocated will not be released. (use delete if you're using new or delete [] if you did new [])

Why does this conversion of infix to postfix notation using stack as an ADT crash?

#include<iostream>
#include<cstring>
using namespace std;
#define MAX 5
struct node
{
char data;
struct node *next;
};
class stack
{
public:
node *top;
stack() //constructor
{
top=NULL;
}
char Top() //return top element without popping
{
return(top->data);
}
int empty() //check empty
{
if(top==NULL)
return(1);
return(0);
}
void push(char x) //push function
{
node *p;
p=new node;
p->data=x;
p->next=top;
top=p;
}
char pop() //pop function
{
node *p;
char x;
p=top;
top=top->next;
x=p->data;
delete(p);
return(x);
}
int precedence(char x) //check precedence of operators
{
if(x=='(')
return 0;
else if(x=='+'||x=='-')
return 1;
else if(x=='*'||x=='/'||x=='%')
return 2;
return 3;
}
void infix_to_postfix(char infix[],char postfix[]);
};
void infix_to_postfix(char infix[],char postfix[])
{
stack s;
char x,token;
int i,j=0;
for(i=0;infix[i]!='\0';i++)
{
token=infix[i];
if(isalnum(token))
postfix[j++]=token;
else
if(token=='(')
s.push(token);
else
if(token==')')
{
while((x=s.pop())!='(')
postfix[j++]=x;
}
else
{
while(s.precedence(token)<=s.precedence(s.Top())&& !s.empty())
postfix[j++]=s.pop();
s.push(token);
}
}
while(!s.empty())
{
x=s.pop();
postfix[j++]=x;
}
postfix[j++]='\0';
}
int main()
{
char infix[30],postfix[30];
cout<<"\nEnter the infix expression::\n";
cin>>infix;
infix_to_postfix(infix,postfix);
cout<<"/nThe equivalent postfix expression is::"<<postfix;
return 0;
}
The above code is giving segmentation fault with gedit in Ubuntu...whereas when the same code when run with turbo C in Windows with the required changes as follows...runs correctly...
#include<stdio.h>
#include<conio.h>
#include<iostream.h>
#include<string.h>
#include<ctype.h>
#include<stdlib.h>
#define MAX 5
struct node
{
char data;
struct node *next;
};
class stack
{
public:
node *top;
stack() //constructor
{
top=NULL;
}
char Top() //return top element without popping
{
return(top->data);
}
int empty() //check empty
{
if(top==NULL)
return(1);
return(0);
}
void push(char x) //push function
{
node *p;
p=new node;
p->data=x;
p->next=top;
top=p;
}
char pop() //pop function
{
node *p;
char x;
p=top;
top=top->next;
x=p->data;
delete(p);
return(x);
}
int precedence(char x) //check precedence of operators
{
if(x=='(')
return 0;
else if(x=='+'||x=='-')
return 1;
else if(x=='*'||x=='/'||x=='%')
return 2;
return 3;
}
void infix_to_postfix(char infix[],char postfix[]);
};
void infix_to_postfix(char infix[],char postfix[])
{
stack s;
char x,token;
int i,j=0;
for(i=0;infix[i]!='\0';i++)
{
token=infix[i];
if(isalnum(token))
postfix[j++]=token;
else
if(token=='(')
s.push(token);
else
if(token==')')
{
while((x=s.pop())!='(')
postfix[j++]=x;
}
else
{
while(s.precedence(token)<=s.precedence(s.Top())&& !s.empty())
postfix[j++]=s.pop();
s.push(token);
}
}
while(!s.empty())
{
x=s.pop();
postfix[j++]=x;
}
postfix[j++]='\0';
}
int main()
{
char infix[30],postfix[30];
cout<<"\nEnter the infix expression::\n";
cin>>infix;
infix_to_postfix(infix,postfix);
cout<<"\nEquivalent postfix expression is::"<<postfix;
getch();
return 0;
}
Why is the problem arising in Ubuntu???
You never check whether your input stack is empty before directly dereferencing top->data. Specifically, this loop:
while(s.precedence(token)<=s.precedence(s.Top())&& !s.empty())
postfix[j++]=s.pop();
s.push(token);
can, and in your case will, dereference an empty stack because you check the empty state after you've already dereferenced the top pointer via s.Top(). You can avoid the inappropriate dereference by using boolean short-circuiting and the proper evaluation order:
while(!s.empty() && s.precedence(token)<=s.precedence(s.Top()))
postfix[j++]=s.pop();
s.push(token);
Input
A*(B+C/(D-A))
Output
The equivalent postfix expression is::ABCDA-/+*
That said, this is extremely brittle. Unless specifically instructed to do so there is no reason you shouldn't be using a custom stack in the first place, as the standard adapter std::stack<> will remove about 90% of this code, and I strongly suggest taking advantage of that.
Finally, this is flat-out bug. Windows or Ubuntu makes no difference. It invokes undefined behavior. That it didn't crash on Windows means you were lucky (or not, since you assumed it was ok because it didn't crash); not right. And in case you're wondering how I noticed this, I saw it in the code, but confirmed it with Valgrind, which confirmed my suspicion immediately.
Using Standard Library for the Heavy Lifting
This gets considerably simpler when you use classes from the standard library for most of the operations, as you can hopefully see below. I kept your algorithm intact, but just used the std::stack adapter and std::string classes for the guts:
#include <iostream>
#include <vector>
#include <stack>
using namespace std;
static int precedence(char x) //check precedence of operators
{
if(x=='(')
return 0;
else if(x=='+'||x=='-')
return 1;
else if(x=='*'||x=='/'||x=='%')
return 2;
return 3;
}
std::string infix_to_postfix(const std::string& infix)
{
std::stack<char> s;
std::string postfix;
for (auto ch : infix)
{
if (isalnum(ch))
postfix.push_back(ch);
else if (ch == '(')
s.push(ch);
else if(ch == ')')
{
while (!s.empty())
{
ch = s.top();
s.pop();
if (ch == '(')
break;
postfix.push_back(ch);
}
}
else
{
while(!s.empty() && precedence(ch)<=precedence(s.top()))
{
postfix.push_back(s.top());
s.pop();
}
s.push(ch);
}
}
while(!s.empty())
{
postfix.push_back(s.top());
s.pop();
}
return postfix;
}
int main()
{
const char infix[] = "A*(B+C/(D-A)+2*(E-F))";
cout << "\nThe equivalent postfix expression is: " << infix_to_postfix(infix);
return 0;
}
Input
A*(B+C/(D-A)+2*(E-F))
Output
The equivalent postfix expression is: ABCDA-/+2EF-*+*

Using a stack to determine if an expression has balanced parentheses

I am working on my last school assignment for the semester and we are being introduced to stacks for the first time but I am having an issue with my program not analyzing the expression properly. Everything executes but the program always comes out with the result that expression is unbalanced. Any clues to point me in the right direction?
//
// main.cpp
// Balanced Parenthesis
#include "StringStack.h"
#include <iostream>
using namespace std;
int main ()
{
StringStack stack;
char entry;
int parCounter = 0;
cout << "This program will accept a string and determine whether it has balanced parenthesis.\n";
cout << "Please type a sentence to be analyzed\n";
while (cin.get (entry) && entry != '\n')
{
stack.push(entry);
}
if (stack.isEmpty()) {
cout << "The stack is empty./n";
}
else{
stack.pop(entry);
if (entry == ')') {
parCounter++;
}
else if(entry == '('){
parCounter--;
}
}
if (parCounter > 0 || parCounter < 0){
cout << "This expression has UNBALANCED parentheses\n";
}
else
{
cout << "This expression has BALANCED parentheses\n";
}
return 0;
}
// StringStack.h
// Balanced Par
#include <iostream>
using namespace std;
#ifndef StringStack_h
#define StringStack_h
//Define our stack class and its contents
class StringStack
{
private:
char *stackArray;
int stackSize;
char top;
public:
StringStack();
~StringStack() {delete[] stackArray;}
void push(char);
void pop(char &);
bool isBalanced();
bool isEmpty();
};
#endif
//Constructor
StringStack::StringStack()
{
stackArray = new char[stackSize];
top = 0;
}
//Function to determine if stack is empty.
bool StringStack::isEmpty()
{
if (top == 0)
return true;
else
return false;
}
//Function to push letters/puncuation onto the stack
void StringStack::push(char letter)
{
//if (isEmpty())
{
top++;
stackArray[top] = letter;
}
//else
//{
//exit(1);
//}
}
//Function to pop letters/puncuation off the stack
void StringStack::pop(char &letter)
{
if (isEmpty())
{
cout << "The stack is empty.\n";
exit(1);
}
else
{
letter = stackArray[top];
top--;
}
}
You're not initialising or setting the member stackSize anywhere. This makes new char[stackSize] undefined behaviour and anything could happen.
And after you fix that, you're only inspecting the top of the stack. You need a loop around the parCount - controlling if to run until the stack is empty.

Array based stack - error in destructor

This is my first pathetic attempt at C++. I did an array based stack in C++ and the destructor is throwing out some memory dump. I can't figure out what went wrong.
#include <stdio.h>
#include <iostream>
#include <exception>
using namespace std;
class FullStackException : public exception {
virtual const char* what() const throw() {
return "Stack is full.";
}
} fsex;
class EmptyStackException : public exception {
virtual const char* what() const throw() {
return "Stack is empty.";
}
} esex;
template <class D>
class ArrayBasedStack {
private:
int t; //t represents top
D *S;
int arrSize;
public:
ArrayBasedStack(int arraySize = 10);
~ArrayBasedStack();
int size(); /*returns the number of elements stored*/
void push(D&); /*inserts an element*/
D pop(); /*removes and returns the last inserted element*/
D top(); /*returns the last inserted element without removing it*/
int isEmpty(); /*indicates whether no elements are stored*/
};
template <class D>
ArrayBasedStack<D>::ArrayBasedStack(int arraySize) {
/* Elements are added from left to right */
S = new D[arraySize];
arrSize = arraySize;
/* t keeps track of the index of the top element */
t = -1;
}
template <class D>
ArrayBasedStack<D>::~ArrayBasedStack() {
if(S != NULL) {
int i = 0;
for(i = 0; i < size(); i++) {
S[i] = NULL;
}
cout << "about to delete S" << endl;
delete[] S;
}
}
template <class D>
int ArrayBasedStack<D>::size() {
return t;
}
template <class D>
void ArrayBasedStack<D>::push(D& data) {
if(t == arrSize) {
throw fsex;
} else {
S[t] = data;
t++;
}
}
template <class D>
D ArrayBasedStack<D>::pop() {
if(isEmpty()) {
throw esex;
}
D element = S[t];
S[t--] = NULL;
return element;
}
/*
* returns true if the stack is empty, false otherwise
*/
template <class D>
int ArrayBasedStack<D>::isEmpty() {
return (t < 0);
}
int main(int argc, char *argv[]) {
char inputs[][10] = {
"str1"
};
char *i = NULL;
ArrayBasedStack<char *> stack;
i = inputs[0];
stack.push(i);
try {
stack.pop();
}
catch(exception& ex) {
cout << "ERR:" << ex.what() << endl;
}
return 0;
}
The problem line is
t = -1;
Should be
t = 0;
because when you add first element, the following code is excecuted
} else {
S[t] = data; // t == -1
t++;
}
The following is the culprit.
template <class D>
void ArrayBasedStack<D>::push(D& data) {
if(t == arrSize) {
throw fsex;
} else {
S[t] = data; // Should be S[++t] = data;
t++; // Comment out this line
}
}
This implemntation assumes that 't' points to the topmost element on the stack rather than to the next available location for push
Note that operator [] and operator ++ have same precedence. Since they associate left-to-right, [] is evaluated before operator ++.
In your implementation, here is the problem. With t being initialized to -1, you are overwriting beyond the array subscript that is at S[-1] which leads to undefined behavior.
At least on my system the problem surfaces while trying to free the memory in destructor of the stack class. This is a classic example of a syptom being visible much after the goof-up has happened
Also would suggest push to take the parameters as D const &