Using pop functions in Stacks - c++

I am running through an example of a static stack implementation from a book, but was not able to obtain the correct value for the last integer popped of the stack. Particularly, the pop(int &) member function in the class IntStack is said to pop the last integer off the stack, and take as input the name of a reference to the integer value that was just "popped".
Upon compiling the code, I find that the input is assigned the value of the address rather than the integer value. I am unsure why this happens, and I am also unsure how the pop member function of the IntStack class assigns this input to the last value stored at index "top."
I've posted the class files for reference (copied from the book - note that these are 2 separate files, one header and one *.cpp). Any help understanding this is soooo greatly appreciated!!!!!
#include <stdio.h>
// Specification file for the IntStack class
#ifndef INTSTACK_H
#define INTSTACK_H
class IntStack
{
private:
int *stackArray; // Pointer to the stack array
int stackSize;
int top;
public:
// The stack size
// Indicates the top of the stack
// Constructor
IntStack(int);
// Copy constructor
IntStack(const IntStack &);
// Destructor
~IntStack();
// Stack operations
void push(int);
void pop(int &);
bool isFull() const;
bool isEmpty() const;
};
#endif
// Implementation file for the IntStack class
#include <iostream>
#include "IntStack.h"
using namespace std;
//************************************************
// Constructor *
// This constructor creates an empty stack. The *
// size parameter is the size of the stack. *
//************************************************
IntStack::IntStack(int size)
{
stackArray = new int[size];
stackSize = size;
top = -1;
}
//***********************************************
// Copy constructor *
//***********************************************
IntStack::IntStack(const IntStack &obj)
{
// Create the stack array.
if (obj.stackSize > 0)
stackArray = new int[obj.stackSize];
else
stackArray = nullptr;
// Copy the stackSize attribute.
stackSize = obj.stackSize;
// Copy the stack contents.
for (int count = 0; count < stackSize; count++)
stackArray[count] = obj.stackArray[count];
// Set the top of the stack.
top = obj.top;
}
//***********************************************
// Destructor *
//***********************************************
IntStack::~IntStack()
{
delete [] stackArray;
}
//*************************************************
// Member function push pushes the argument onto *
// the stack. *
//*************************************************
void IntStack::push(int num)
{
if (isFull())
{
cout << "The stack is full.\n";
}
else
{
top++;
stackArray[top] = num;
}
}
//*****************************************************
// Member function pop pops the value at the top *
// of the stack off, and copies it into the variable *
// passed as an argument. *
//*****************************************************
void IntStack::pop(int &num) {
if (isEmpty())
{
cout << "The stack is empty.\n";
}
else
{
top--;
}
}
//***************************************************
// Member function isFull returns true if the stack *
// is full, or false otherwise. *
//***************************************************
bool IntStack::isFull() const
{
bool status;
if (top == stackSize - 1)
status = true;
else
status = false;
return status;
}
//*****************************************************
// Member function isEmpty returns true if the stack *
// is empty, or false otherwise. *
//*****************************************************
bool IntStack::isEmpty() const
{
bool status;
if (top == -1)
status = true;
else
status = false;
return status;
}

pop method is missing num assignment
void IntStack::pop(int &num) {
if (isEmpty())
{
cout << "The stack is empty.\n";
}
else
{
num=stackArray[top];
top--;
}
}

Related

Print elements of the stack from top to bottom with C++

I'm currently working with stack data structure in C++, and i'm trying to initialize the stack by using arrays.
Stack has a specific size and i want to print elements of the stack from top to bottom using for loop.
Here is my code:
#include <iostream>
using namespace std;
template<class T>
class Stack {
private:
int top, size;
T* stack = new T[size];
public:
Stack(int size) {
this->top = -1;
this->size = size;
}
void push(int data) {
if (top >= size - 1) {
return;
}
else {
++top;
stack[top] = data;
}
}
void pop() {
if (top < 0) {
return;
}
else {
--top;
}
}
void print() {
for (int i = top; i >= 0; i--) {
cout << stack[i] << endl;
}
}
};
int main() {
Stack<int> stack(20);
stack.push(12);
stack.push(3);
stack.push(4);
stack.push(7);
stack.print();
return 0;
}
After compiling i get all of my elements printed successfully, but unfortunately at the end the program throws an exception ntdll.pdb not loaded.
Thanks in advance.
The order of construction is wrong. The member variables are initialized before the constructor body is entered, so size contains an arbitrary value at that time it's read to determine the size of the array. Furthermore you forgot to delete the array.
To fix the initialization order, initialize the array in the constructor and add a destructor. In the following code I simply use std::unique_ptr which automatically deletes the array contained in it.
Furthermore it's preferrable to not use the same identifier for parameters and members; a prefix usually is added to member variables to avoid this
#include <memory>
...
template<class T>
class Stack {
private:
size_t m_size;
int m_top;
std::unique_ptr<T[]> m_stack;
public:
Stack(size_t size)
: m_stack(new T[size]), m_size(size), m_top(-1)
{
}
...

C++ Function already has a body [duplicate]

This question already has answers here:
Including .cpp files
(10 answers)
Why should I not include cpp files and instead use a header?
(14 answers)
Closed 2 years ago.
I have an error where "function already has a body" for my constructors and member functions when I have not repeated any of the bodies. The error code is C2084:
void Func(int);
void Func(int) {} // define function
void Func(int) {} // C2084 second definition
I have not created duplicate functions similar to what is shown on the visual studios error page. here is the code below if anybody knows a solution to this error I would greatly appreciate it.
Here is the Stack.h:
//CONTENTS: Declares Class SStack, with data members, contructors and member function prototypes
//If you want, you can make minor changes to this header file
#ifndef _StackClass_
#define _StackClass_
#include <cstdlib>
#include <string>
#include <iostream>
using namespace std;
class SStack
{
public:
// Constructor
SStack( int cap);
// Copy Constructor
SStack( const SStack& s );
~SStack( ); //destructor
// The member function push: Precondition: the stack is not full.
void push ( const std::string s);
// The member function pop: Precondition: the stack is not empty.
void pop ();
// The member function top: Precondition: the stack is not empty.
string top () const;
bool IsEmpty () const;
//printing all the elements in the stack
void print() const;
int size() const;
int getCapacity() const;
private:
int capacity; // Capacity is the maximum number of items that a stack can hold
std::string* DynamicStack;
int used; // How many items are stored in the stack
};
#include "SStack.cpp"
#endif
Here is the SStack.cpp:
#include <iostream>
#include "SStack.h"
SStack::SStack(int cap)
{
DynamicStack = new string[cap];
this->capacity = cap;
this->used = -1;
}
SStack::SStack(const SStack& s)
{
capacity = s.capacity;
DynamicStack = new string[capacity];
used = s.used;
for (int i = 0; i < used; i++) {
DynamicStack[i] = s.DynamicStack[i];
}
}
SStack::~SStack()
{
}
void SStack::push(const std::string s)
{
if (used >= capacity - 1) {
cout << "Stack overflow" << endl;
}
else {
this->used++;
DynamicStack[used] = s;
cout << s << "pushed onto the stack" << endl;
}
}
void SStack::pop()
{
if (used < 0) {
cout << "stack underflow" << endl;
}
else {
string s = DynamicStack[used];
this->used--;
}
}
string SStack::top() const
{
if (used < 0) {
cout << "stack is empty" << endl;
return 0;
}
else {
string s = DynamicStack[used];
return s;
}
}
bool SStack::IsEmpty() const
{
if (used < 0) {
return true;
}
else {
return false;
}
}
void SStack::print() const
{
for (int i = used; i >= 0; i--) {
cout << DynamicStack[used] << endl;
}
}
int SStack::size() const
{
return used;
}
int SStack::getCapacity() const
{
return capacity;
}
You have an #include "SStack.cpp" in your header file.
Don't do that.
Source files (.cpp files) include header files. Never the other way around.

Is an isFull() function for a Dynamic Array Container Class needed?

I'm having a bit of trouble wrapping this around my head; I used the debugger in VS to go through my code. I realized that when I call the insertBack() function in main() the elements aren't inserted since the condition if (!isFull) isn't met--returning false causing the insertion to not happen. I tried removing the condition and got some errors regarding my code trying to insert a number into an invalid portion of the array. While going through this, I started to ask myself is the isFull() function required since a dynamic array can be resized; but, how can it be full if this is the case? I looked a bit into vectors on cpprefrence and didn't find an isFull() member function.
#include <iostream>
template<typename T>
class container
{
template <typename T2>
friend std::ostream& operator<<(std::ostream& out, const container<T2> &cobj);
// Postcondition: contents of the container object cobj is displayed
public:
container();
// Postcondition: an empty container object is created with data members arr set to NULL, n set to -1 and Capacity set to 0
~container();
// Destructor; required as one of the Big-3 (or Big(5) because of the presence of a pointer data member. Default version results in
// memory leak!
// Postcondition: dynamic memory pointed to by arr has been release back to the “heap” and arr set to NULL or nullptr
// In order to see the action, message "destructor called and dynamic memory released!" is displayed
bool isEmpty() const;
// Postcondition: returns true is nothing is stored; returns false otherwise
bool isFull() const;
// Postcondition: returns true if arr array is filled to capacity; returns false otherwise
int size() const;
// Postcondition: returns the size or the number of elements (values) currently stored in the container
int capacity() const;
// Postcondition: returns the current storage capacity of the container
bool insertBack(const T& val);
// Postcondition: if container is not full, newVal is inserted at the end of the array;
// otherwise, double the current capacity followed by the insertion
bool deleteBack();
// Precondition: The array must not be empty
// Postcondition: the last element stored in the array is removed! size of the container is decremented by 1, capacity unchanged
void clear();
// Postcondition: all elements in arr of calling container object are cleared and the dynamic memory is released back to “heap”
private:
void allocate(T* &temp);
// Postcondition: if Capacity = 0, allocate a single location; otherwise the current capacity is doubled
T *arr;
int Capacity; // Note: Capital 'C' as capacity is used as a function name
int n; // size or actual # of values currently stored in the container; n <= SIZE
};
template<typename T2>
std::ostream& operator<<(std::ostream& out, const container<T2> &cobj)
{
std::cout << "Currently it contains " << cobj.size() << " value(s)" << std::endl
<< "Container storage capacity = " << cobj.capacity() << std::endl
<< "The contents of the container:" << std::endl;
if (cobj.isEmpty())
{
std::cout << "*** Container is currently empty!" << std::endl;
}
else
{
for (int i=0; i<cobj.size(); ++i)
{
std::cout << cobj.arr[i];
}
}
return out;
}
template<typename T>
container<T>::container()
{
arr = nullptr;
Capacity = 0;
n = 0;
}
template<typename T>
container<T>::~container()
{
delete arr;
arr = nullptr;
std::cout << "Destructor called! (this line is normally not displayed)" << std::endl;
}
template<typename T>
bool container<T>::isEmpty() const
{
return n==0;
}
template<typename T>
bool container<T>::isFull() const
{
return n==Capacity;
}
template<typename T>
int container<T>::capacity() const
{
return Capacity;
}
template<typename T>
int container<T>::size() const
{
return n;
}
template<typename T>
bool container<T>::insertBack(const T& val)
{
if (!isFull())
{
n++;
arr[n-1] = val;
return true;
}
else
{
return false;
}
}
template<typename T>
bool container<T>::deleteBack()
{
if (!isEmpty())
{
n--;
return true;
}
else
{
return false;
}
}
template<typename T>
void container<T>::clear()
{
if (!isEmpty())
{
n = 0;
return true;
}
else
{
return false;
}
}
template<typename T>
void container<T>::allocate(T* &temp)
{
if (Capacity==0)
{
temp = new T;
}
else
{
return Capacity*2;
}
}
int main()
{
container<int> a1;
std::cout << a1 << std::endl;
std::cout << "Currently, the container object contains 0 element(s) or 0 value(s)" << std::endl;
std::cout << "\nWe now insert 3 values at the back of the array, one at a time:" << std::endl;
const int num = 3;
for (int i=0, c=0; i<=num; ++i, c+=10)
{
a1.insertBack(c);
}
std::cout << a1;
}
I think that having an isFull method does not make sense, since your dynamic container is not limited in capacity. Instead, you can use the size and capacity methods to track the state of the container.
If you want to implement a vector and want to check if size smaller than or equals to capacity, then decide whether to resize it, you can wrapper size > = capacity as a private isFull() function. But I think it makes no sense to set it public.

Virtual Functions Polymorphism and Inheritance

I know the title sucks... but I have no clue what actual issue I have got at my hands...
I have defined a base class for linked lists and a specialized class that inherits the base class.
Base:
list.h
#ifndef LIST_H
#define LIST_H
#include <string>
#include "../../declarations.h"
#include "element.h"
class List: public Element{
/*
* #brief is a generic list class, designed to be inherited by more
* specialised list emulating classes.
*/
public: // methods
/// generates empty list.
List(){
init();
cout << "defining List" << endl;
}
/// Removes first list element
bool remove_first(){
if (!is_empty()){
Element* newFirst = first;
delete first;
first = newFirst->next;
return true;
}
else{
std::cerr << "list already empty" << endl;
return false;
}
}
/// removes last list element
bool remove_last(){
// store length fo list in min_len for switch
unsigned int min_len = 0;
if (!is_empty()){
if ((first->next) != 0){
min_len = 2;
}
else {
min_len = 1;
}
}
// as switch doesn't allow for comparisons, map any value greater
// 1 to 2 if (min_len>1) min_len = 2;
switch (min_len){
case (2):{
// Iterate over list, always look two elements ahead.
// If the next element points to 0 you have found your new last
// element (the current next to last one). Delete current-> next
// to remove the last element and let the new last one point to
// zero.
Element* current = first;
while((current->next)->next != 0){
current = (current->next);
}
delete (current->next);
current->next = 0;
return true;
}
// if the list contaisn only one element use remove_first()
// as the logic for that case is already present there
case (1): return remove_first();
case (0):{
std::cerr << "list already empty" << endl;
return false;
}
}
}
// Declare several virtual functions for appending elements
// that get defined in the iheriting classes.
virtual void append_front(int i){};
virtual void append_front(char c){};
virtual void append_front(std::string s){};
virtual void append_back(int i){};
virtual void append_back(char c){};
virtual void append_back(std::string s){};
/// todo
std::string head(){}
/// returns length of list
unsigned length(){
unsigned counter = 0;
Element* current = first;
while(current != 0) {
++counter;
current = current->next;
}
return counter;
}
/// determines whether list is empty
bool is_empty(){
return first == 0;
}
// printing depends on type of list, so this method gets defined in
// inheriting class
virtual void print(){};
private: // methods
void init(){
// initialise empty list with a NULL pointer
first = 0;
}
protected: // data members
/// points to first list element or zero, if list is empty
Element* first;
};
#endif
Derived:
transitionsList.h
#ifndef TRANSITION_LIST_H
#define TRANSITION_LIST_H
#include "../../../generic/list.h"
#include "../../elements/transition/transition.h"
class TransitionList: public List {
public:
void append_front(char c){
// generate list element and store in pointer e
Element* e;
e = new Transition();
// store parameter c in the object *e points to
e->set_content(c);
// Either list is empty. In thet case object at &e becomes first
// list element and also the last.
// Or list wasn't empty and e->next points to the current first, then
// object *e points to becomes first.
if (is_empty()) {
first = e;
e->next = 0;
}
else {
e->next = first;
first = e;
}
}
void append_back(char c){
if (is_empty()) {
append_front(c);
}
else {
Element* e;
e = new Transition();
e->set_content(c);
e->next = 0;
// Go through the list until you find the last element, let it
// then ppint to the new last element.
Element* current = first;
while(current->next != 0) {
current = current->next;
}
current->next = e;
}
}
void print(){
cout << "[";
// go through the list, starting with first element
Element* current = first;
// as long as the last list element is not the current one, keep
// printing elements.
while (current != 0) {
cout << " " << current->get_content();
// let current be the next of current current, to move
// through the list
current = current->next;
} // while
cout << " ]";
}
};
#endif
These two depend on a few other classes:
element.h:
#ifndef ELEMENT_H
#define ELEMENT_H
#include "../../declarations.h"
class State;
class Element{
/*
* #brief is a generic list element class, designed to be inherited by
* more specialised list element classes.
*/
public:
Element(){}
virtual ~Element(){}
virtual void set_content(int i){};
virtual void set_content(char c){};
virtual void set_content(std::string s){};
virtual char get_content() = 0;
Element* next; ///< is the pointer to the next transition in the list
};
#endif
state.h:
#ifndef STATE_H
#define STATE_H
#include "../../declarations.h"
class List;
class State{
/**
* #brief is a class emulating a trie state
*/
public: // methods
State(){
cout << "defining State" << endl;
init();
}
private: // methods
void init(){
}
private: // variables
// Pointer required due to forward declarations
List* transitions; ///< is the list of states dominated by THIS.
// count stores how often the word the current path codes for has been
// found in the training data.
int count; ///< is the number of occurances of some word in this path.
};
#endif
and transition.h
#ifndef TRANSITION_H
#define TRANSITION_H
#include "../../../generic/element.h"
#include "../../state.h"
typedef char cont;
class Transition: public Element {
public:
void set_content(cont c){
content = c;
};
cont get_content(){
return content;
};
State* successor;
Transition* next; ///< is the pointer to the next transition in the list
protected:
cont content; ///< is the character this transition codes for
};
#endif
When I now run this cpp-file:
list_test.cpp:
#include "transitionList.h"
int main(){
TransitionList* derivedList;
List *baseList = &derivedList;
}
I get the error:
list_test2.cpp:5:8: error: cannot initialize a variable of type 'List *' with an rvalue of type 'TransitionList **'
Which I don't understand, because I am under the (apparently phony) impression, that this would be analogous to what I saw in this tutorial:
https://youtu.be/DudHooleNVg?t=4m59s
Where is
int main(){
TransitionList* derivedList;
List *baseList = &derivedList;
}
not analogous to
int main(){
Ninja* n;
Enemy *enemy1 = &n;
}
:/ Very confused.

Popping the top 2 values from a stack, adding them and push them back

Here's what I came up with, I just want the program to pop the first 2 values in the stack, calculate them and push the back into the stack...I've already created the functions required but there seem to be a problem with the function that adds the two numbers.
#include <iostream>
using namespace std;
int Maxlenght=5;
class stackhouse{
private:
int *CreateArray;
int top;
public:
stackhouse();
bool IsEmpty();
bool IsFull();
void constructor();
void Push(int);
void Pop(int);
void Sum();
void Sub();
};
stackhouse::stackhouse(){
CreateArray= new int[Maxlenght];
top=-1;
}
bool stackhouse::IsEmpty()
{
if (top==-1) return 1;
else return 0;
}
bool stackhouse::IsFull(){
if (top==Maxlenght-1) return 1;
else return 0;
}
void stackhouse::Push(int number){
top++;
CreateArray[top]=number;
}
void stackhouse::Pop (int number){
number=CreateArray[top];
top--;
}
void stackhouse::Sum(){
int number=7,sum=5;
Pop(sum);
Pop(number);
sum+=number;
Push(sum);
cout<<sum;
}
void main(){
int number;
stackhouse stack1;
stackhouse();
cout<<"Please fill the stack...";
stack1.Push(5);
stack1.Push(2);
cout<<"The sum is...";
stack1.Sum();
}
The Pop function needs to either return number or pass number by reference; otherwise, the assignment to number has no effect.
void stackhouse::Pop(int& number) { // <-- add the &
number = CreateArray[top];
top--;
}
Or
int stackhouse::Pop() {
int number = CreateArray[top];
top--;
return number;
}
(Note that the second way requires you to write sum = Pop() instead of Pop(sum).)
Passing a parameter by value to the pop() method is pointless. It needs to return a value.