Template Stack and LIFO C++ - c++

So I'm trying to learn about Templates and the Fifo and Lifo stack stuff. I've been playing around with some code that deals with this, and I can get the int data to do what I want for testing but I can't for the life of me figure out how to get this to work with a string.
The way I have the code keeps crashing on me, but doesn't give me any errors, so I thought I'd pop in here and see if anybody could tell me what I'm doing wrong. Here's my code:
-----------//my header//---------------------
#include <stdlib.h>
#include <iostream>
#include <string>
#ifndef STACK_H_
#define STACK_H_
template<class T>
class StackTest
{
private:
unsigned int maxSize;
T *stackData;
int top;
public:
StackTest(int size){
stackData = new T[size];//to hold the T ‌type data items
top = -1;//no items on the stack
maxSize = size;//set maximum size that stack can hold
}
virtual ~StackTest(){}
int count(){
return top + 1;
}
bool isEmpty(){
return top == -1 ? true : false;
}
bool isFull(){
return top == maxSize - 1 ? true : false;
}
T* peek(){
if(!isEmpty())//check for empty
return &stackData[top - 1];
}
T* pop(){
if(!isEmpty()){
top -= 1;//decrease the top by 1 to indicate the delete
return &stackData[top];//return deleted item
}
return NULL;
}
void push(T* item){
stackData[top++] = *item;//insert to data array and increase the top by one
}
};
#endif /* STACK_H_ */
-----------//my main//---------------
#include <iostream>
#include <string>
#include "Pair.h"
using namespace std;
int main() {
int dataTest;
string strTest;
StackTest<int> intStack(10);
StackTest<string> stringStack(50);
//Insert data into the stack
dataTest = 3;
intStack.push(&dataTest);
dataTest = 4;
intStack.push(&dataTest);
dataTest = 5;
intStack.push(&dataTest);
dataTest = 6;
intStack.push(&dataTest);
strTest = "test";
stringStack.push(&strTest);
//Show the top item
cout << *intStack.peek() << endl;
cout << *stringStack.peek() << endl;
//Pull the top item out (twice)
intStack.pop();
intStack.pop();
//Show the new top item
cout << *intStack.peek() << endl;
return 0;
}
So if anyone feels like giving me some pointers I would really appreciate it, thanks.

There are a few issues with your implementation. One of the most subtle is in the push() member function:
void push(T* item){
stackData[top++] = *item; //insert to data array and increase the top by one
// ^^
// You want pre-increment here!
}
This is incrementing top and using the old value as an index into stackData. Since top is -1 when the stack is empty, your program is actually doing:
stackData[-1] = *item;
top = 0;
Needless to say that the first assignment results in undefined behavior.
Another source of undefined behavior is the peek() member function, which does not return anything when the stack is empty:
T* peek(){
if(!isEmpty())//check for empty
return &stackData[top - 1];
}
Per paragraph 6.6.3/2 of the C++11 Standard:
[...] Flowing off the end of a function is equivalent to a return with no value; this results in undefined
behavior in a value-returning function.
But that's not the only issue: the other problem is with the access of stackData:
return &stackData[top - 1];
When top is not equal to or greater than one, this will also result in undefined behavior, since you would be taking the address of a (non-)object located at a negative address in the array.
Also, I suggest to rewrite isEmpty() and isFull() as follows:
bool isEmpty(){
return (top == -1);
}
bool isFull(){
return (top == maxSize - 1);
}
As a general advice, consider not using the value -1 for top when the stack is empty. As Ben Voigt mentions in the comments, this is leading you to a lot of off-by-one errors.
Also, as pointed out by DyP, your destructor is not freeing the memory allocated in the constructor, so your StackTest object is leaking memory. And after doing that, since we're at it, you may want to have a look at the so-called Rule of Three, that your program would be violating.

Related

Member variable resetting back to 0

When running through the test the count variable from the class stack1 gets reset back to 0 when using its pop function. Strangely however, during the push loop, the count increases as intended but when pop occurs, the count gets reset back to 0 and subtracts into the negatives from there. Is there something I'm forgetting?
#include <iostream>
using namespace std;
class TheStack
{
public:
TheStack();
void push(int);
int pop();
bool isEmpty();
private:
const int MaxSize = 10;
int arr[10];
int count;
};
TheStack::TheStack()
{
count = 0;
}
void TheStack::push(int userInput)
{
if (count >= MaxSize)
{
cout << "Stack is full." << endl;
}
else
{
arr[count] = userInput;
count+=1;
}
}
int TheStack::pop()
{
if (isEmpty())
{
cout << "Stack is empty." << endl;
}
else
{
int temp = arr[count];
arr[count] = NULL;
count-=1;
return temp;
}
}
bool TheStack::isEmpty()
{
if (count == 0)
{
return true;
}
else
{
return false;
}
}
int main()
{
TheStack stack1;
if (stack1.isEmpty())
{
cout << "isEmpty() works" << endl;
}
stack1.pop();
for (int i = 0; i < 10; i++)
{
stack1.push(i);
}
stack1.push(0);
stack1.pop();
stack1.pop();
stack1.pop();
stack1.pop();
system("pause");
}
When you do push you first save the data into the array and then increment count. This means that in order to properly do pop you need to work in reverse: first decrement count and only then read data from the array.
But in the code you are doing it backwards. When the stack is full, count is at max value (10 in your case), and your arr[count] = NULL; writes beyond the array boundary. This causes undefined behavior and, in particular, destroys your count value. (This is why it suddenly becomes 0.)
Also:
arr[count] = NULL; makes no sense. NULL is supposed to be used in pointer contexts, not in integer contexts. This is not even guaranteed to compile.
What is the point of that anyway? Initially your array contains garbage above the current top of the stack. Why do you suddenly care to clean it up after doing pop?
Not all control paths of pop() return value. This is undefined behavior in itself.
const int MaxSize = 10; in the class definition is a C++11 feature. Since you are already using C++11, you can do the same for count. Just do int count = 0; right inside the class definition and you will not have to write the constructor explicitly.
Although in your implementation MaxSize would make more sense as a static const class member. In that case you'll also be able to declare your array as int arr[MaxSize];.
You must first decrease count and then access arr[count] in int TheStack::pop(). Now you get access above the last pushed element, event out of bound of array if the stack is full.

Implementation of stack in C++ without using <stack>

I want to make an implementation of stack, I found a working model on the internet, unfortunately it is based on the idea that I know the size of the stack I want to implement right away. What I want to do is be able to add segments to my stack as they are needed, because potential maximum amount of the slots required goes into 10s of thousands and from my understanding making the size set in stone (when all of it is not needed most of the time) is a huge waste of memory and loss of the execution speed of the program. I also do not want to use any complex prewritten functions in my implementation (the functions provided by STL or different libraries such as vector etc.) as I want to understand all of them more by trying to make them myself/with brief help.
struct variabl {
char *given_name;
double value;
};
variabl* variables[50000];
int c = 0;
int end_of_stack = 0;
class Stack
{
private:
int top, length;
char *z;
int index_struc = 0;
public:
Stack(int = 0);
~Stack();
char pop();
void push();
};
Stack::Stack(int size) /*
This is where the problem begins, I want to be able to allocate the size
dynamically.
*/
{
top = -1;
length = size;
z = new char[length];
}
void Stack::push()
{
++top;
z[top] = variables[index_struc]->value;
index_struc++;
}
char Stack::pop()
{
end_of_stack = 0;
if (z == 0 || top == -1)
{
end_of_stack = 1;
return NULL;
}
char top_stack = z[top];
top--;
length--;
return top_stack;
}
Stack::~Stack()
{
delete[] z;
}
I had somewhat of a idea, and tried doing
Stack stackk
//whenever I want to put another thing into stack
stackk.push = new char;
but then I didnt completely understand how will it work for my purpose, I don't think it will be fully accessible with the pop method etc because it will be a set of separate arrays/variables right? I want the implementation to remain reasonably simple so I can understand it.
Change your push function to take a parameter, rather than needing to reference variables.
To handle pushes, start with an initial length of your array z (and change z to a better variable name). When you are pushing a new value, check if the new value will mean that the size of your array is too small (by comparing length and top). If it will exceed the current size, allocate a bigger array and copy the values from z to the new array, free up z, and make z point to the new array.
Here you have a simple implementation without the need of reallocating arrays. It uses the auxiliary class Node, that holds a value, and a pointer to another Node (that is set to NULL to indicate the end of the stack).
main() tests the stack by reading commands of the form
p c: push c to the stack
g: print top of stack and pop
#include <cstdlib>
#include <iostream>
using namespace std;
class Node {
private:
char c;
Node *next;
public:
Node(char cc, Node *nnext){
c = cc;
next = nnext;
}
char getChar(){
return c;
}
Node *getNext(){
return next;
}
~Node(){}
};
class Stack {
private:
Node *start;
public:
Stack(){
start = NULL;
}
void push(char c){
start = new Node(c, start);
}
char pop(){
if(start == NULL){
//Handle error
cerr << "pop on empty stack" << endl;
exit(1);
}
else {
char r = (*start).getChar();
Node* newstart = (*start).getNext();
delete start;
start = newstart;
return r;
}
}
bool empty(){
return start == NULL;
}
};
int main(){
char c, k;
Stack st;
while(cin>>c){
switch(c){
case 'p':
cin >> k;
st.push(k);
break;
case 'g':
cout << st.pop()<<endl;
break;
}
}
return 0;
}

Frustrating pointer error

For the life of me, I can't figure out what is going wrong. I know the error is occurring in the function marked displayQueue below, but all the syntax and logic seems correct.
Visual studio is giving me the error: "Unhandled exception at 0x00215A86 in ex11_1.exe: 0xC0000005: Access violation reading location 0xCDCDCDE1." But really, I have no idea what this is referring to...
#include <iostream>
#include <cstdlib>
#include <string>
using namespace std;
struct QueueNode {
string data;
QueueNode *link;
};
typedef QueueNode* QueueNodePtr;
class Queue {
public:
// Constructors/Destructor.
Queue();
Queue(const Queue& aQueue);
// Accessors.
bool empty() const;
void displayQueue ();
// Mutators.
void add(string item);
string remove(); // This should probably be replaced with pop and top - especially for displayQueue... empty() in functions can be replaced with count == 0. Yes, I will do this.
private:
QueueNodePtr front; // Points to head of linked-list queue.
QueueNodePtr back; // Points to tail of linked-list queue.
size_t count;
};
int main () {
Queue myQueue;
myQueue.add("abc");
myQueue.add("def");
myQueue.add("ghi");
myQueue.displayQueue(); // The error is here somewhere. abc is printed and but nothing else.
system("pause");
return 0;
}
Queue::Queue() {
front = NULL;
back = NULL;
count = 0;
}
Queue::Queue(const Queue& aQueue) {
front = aQueue.front;
back = aQueue.back;
count = aQueue.count;
}
bool Queue::empty() const {
if (count == 0) {
return 1;
} else {
return 0;
}
}
void Queue::displayQueue () {
// There is a problem here somewhere...
QueueNodePtr here = front;
for (int i = 0; i < count; i++) {
cout << here->data << endl;
here = here->link;
}
}
void Queue::add(string item) {
QueueNodePtr newNode;
newNode = new QueueNode;
if (count == 0) {
// If inserted in an empty queue, back and front point to same element.
newNode->data = item;
// newNode->link = NULL; // Not sure this part is even necessary.
back = newNode;
front = back;
} else {
// Otherwise, leave front pointer where it's at.
newNode->data = item;
newNode->link = back->link;
back = newNode;
}
count ++;
}
string Queue::remove() {
string returnString;
if (count == 0) {
return returnString;
} else if (count == 1) {
returnString = front->data;
front = NULL;
back = front;
count--;
return returnString;
} else {
returnString = front->data;
front = front->link;
count--;
return returnString;
}
}
EDIT: If anyone can give me any tips on using the debugger to solve problems like this, or give me a link that might explain this it would be greatly appreciated.
The error is on this line, but for the sake of learning, I won't give the correct version, just a few hints:
newNode->link = back->link;
At the point where this code is being executed, which node does back point to? What does its link point to? Whose node's link do you need to modify?
As for finding this yourself, you could have used the debugger to figure out which line causes the crash; this would have indicated that something is wrong with a link value.
P.S. Your copy constructor doesn't actually copy the linked list; it just creates a new Queue object that points to the same linked list, so if you add an element to the copy, it will show up in the original Queue.
An access violation at address 0xCDCDCDCD means that your program loaded a pointer from uninitialized storage and then dereferenced it. Microsoft's debugging allocator uses this pattern for newly allocated uninitialized storage, and in a suitable compilation mode, also for stack locations. If you treat such uninitialized storage as a pointer variable, the pattern is recognizeable in that pointer. Moreover, it is almost certainly an invalid pointer that will trigger an exception. So the benefit is that the use of the invalid pointer is caught quickly, and the pattern tells you that the cause is quite likely uninitialized storage (though this is not 100% conclusive).
For example:
struct contains_pointer { char *str; } *ptr = malloc(sizeof *ptr);
strcpy(ptr->str, "abc"); // ptr->str is uninitialized
Or:
int *pint;
*pint = 0; // pint is uninitialized
To have the compiler and library overwrite uninitialized storage with a pattern like CDCDCD... can be quite helpful. You should pinpoint the location of the crash with the debugger, and then work backward from there: where did the pointer value originate and why wasn't it initialized.
(A bad pointer to the address CDCDCDCD could result in other ways: sheer fluke (unlikely) or a use-after-free bug: the program frees some memory but continues to keep a pointer to it, without using it for a while. The memory is then re-allocated to some other part of the program, and marked uninitialized, and by chance, the original user of the pointer makes a use of it, loading a pointer value from the memory. At that moment, a CDCDCDCD pointer results, so it looks like a use-before-init bug, when in fact it's a use-after-free bug. Debugging based on "memory poisoning" patterns is not accurate!)

C++ Priority Queue, logical error, can't figure out

I'm implementing a simple priority queue in C++.
However when it runs, it prints out gibberish numbers.
Am I somehow trying to access invalid entries in the array in my code?
Below is the code.
Also, is my "remove" function somehow not doing its job? Conceptually, shall I be putting null into the first entry and return whatever was just erased?
Thanks.
[Priority.h]
#ifndef Priority_h
#define Priority_h
class Priority
{
public:
Priority(void);
Priority(int s);
~Priority(void);
void insert(long value);
long remove();
long peekMin();
bool isEmpty();
bool isFull();
int maxSize;
long queArray [5];
int nItems;
private:
};
#endif
[Priority.cpp]
#include <iostream>
#include <string>
#include <sstream>
#include <stack>
#include "Priority.h"
using namespace std;
Priority::Priority(void)
{
}
Priority::Priority(int s)
{
nItems = 0;
}
Priority::~Priority(void)
{
}
void Priority::insert(long item)
{
int j;
if(nItems==0) // if no items,
{
queArray[0] = item; nItems++;
}// insert at 0
else // if items,
{
for(j=nItems-1; j=0; j--) // start at end,
{
if( item > queArray[j] ) // if new item larger,
queArray[j+1] = queArray[j]; // shift upward
else // if smaller,
break; // done shifting
} // end for
queArray[j+1] = item; // insert it
nItems++;
} // end else (nItems > 0)
}
long Priority::remove()
{
return queArray[0];
}
long Priority::peekMin()
{
return queArray[nItems-1];
}
bool Priority::isEmpty()
{
return (nItems==0);
}
bool Priority::isFull()
{
return (nItems == maxSize);
}
int main ()
{
Priority thePQ;
thePQ.insert(30);
thePQ.insert(50);
thePQ.insert(10);
thePQ.insert(40);
thePQ.insert(20);
while( !thePQ.isEmpty() )
{
long item = thePQ.remove();
cout << item << " "; // 10, 20, 30, 40, 50
} // end while
cout << "" << endl;
system("pause");
}
Here is one error:
for(j=nItems-1; j=0; j--) // start at end,
^ this is assignment, not comparison.
I am also not convinced that there isn't an off-by-one error in
queArray[j+1] = item; // insert it
Finally, your default constructor fails to initialize nItems.
There could be further errors, but I'll stop at this.
I agree with the other answers here, but I would add this:
Your "Remove" method isn't actually removing anything - it is just returning the first element - but it doesn't do anything to the array itself.
Edited to say that your insert method needs some work - it may or may not write over the end of the array, but it is certainly confusing as to what it is doing.
Try initializing your queue array in the constructor.

C++ Stack Push/Print Implementation

I'm trying to make a stack implementation in C++ but when I try to print the stack,
it just prints the first element instead of the whole stack.
I've tested it and I'm pretty sure that my Push function is right, but I'm not sure.
#include <stdio.h>
#include <stdlib.h>
#include "stack.h"
int main(){
StackElement *stack = new StackElement();
stack->data = 20;
stack->Push(30,stack);
stack->Push(40,stack);
stack->Print(stack);
}
#include <stdio.h>
#include <stdlib.h>
class StackElement{
public:
int data;
StackElement* next;
StackElement();
void StackElement::Push(int value, StackElement *oldElement);
void StackElement::Print(StackElement *element);
};
StackElement::StackElement(){
next = NULL;
}
void StackElement::Push(int value, StackElement *oldElement){
StackElement *newElement = new StackElement();
newElement->data = value;
printf("Element added to stack: %d\n", newElement->data);
oldElement->next = newElement;
}
void StackElement::Print(StackElement *element){
while(element->next != NULL){
printf("%d\n",element->data);
element = element->next;
}
}
Your code kept loosing the previous pushed element, leaking memory, as #Beta described.
I suggest comparing my code below to your code. You'll see, I've moved the handling of the stack elements outside, just to be able to keep track of the first element. Also, notice that there is no pointer in the main function. That is what we expect from a class.
Stack_element is a struct really as there's not much point in making the Stack_element itself encapsulated, it is just an implementation detail of Stack.
So here's my code derived from yours
#include<iostream>
struct Stack_element{
int data;
Stack_element*next;
};
class Stack{
private:
Stack_element*last_data, first_data;
public:
Stack():last_data(NULL), first_data(NULL){}
void push(int data);
void print() const;
};
void Stack::push(int data)
{
Stack_element*p=new Stack_element();
p->data=data;
p->next=NULL;
if(last_data)
last_data->next=p;
else // empty stack
first_data=p;
last_data=p;
}
void Stack::print()
{
for(Stack_element*p=first_data;p;p=p->next)
std::cout << p->data << std::endl; // ** Do not use printf in c++. Ever. **
}
and in the main function just call
Stack stack;
stack.push(30);
stack.push(40);
stack.print();
REMARK: For a C++ish print you might want to do an ostream& print(ostream& os) instead, where
std::ostream& Stack::print(std::ostream& os)
{
for(Stack_element*p=first_data;p;p=p->next)
os << p->data << std::endl;
return os;
}
just to be able to write std::cout << stack.print() << std::endl;. The benefit of this is that you can easily redirect to a file.
std::ofstream ofs("yourfile.txt");
ofs << stack.print() << std::endl; // prints to file instead of screen.
Suppose this much works as planned:
StackElement *stack = new StackElement();
stack->data = 20;
stack->Push(30,stack);
Now your data looks like [20]->[30]
Now you attempt
stack->Push(40,stack);
So the Push method creates a new StackElement, gives it the value 40, and sets Stack to point to it: [20]->[40]. Notice that [30] has been lost.
Then the Print function:
while(element->next != NULL){
printf("%d\n",element->data);
element = element->next;
}
If there is only one element (whose next is NULL), this function will quit and print nothing. If there are two, this function will print the data of the first, then quit. And there will never be more than two, as long as Push has that bug.