Home > OS >  why is the stackdisplay function not working
why is the stackdisplay function not working

Time:03-30

this is a simple program for using a stack. it basically does all the stack operations, when I run it the programming is not working for some reason and I can't figure out the reason why. also, is there any way I can improve this current code? this is the program code here

//

#include <iostream>

using namespace std;



struct stack {
    int top = -1;
    int size;
    int* p;

} *stack;

struct stack* createStack(int size)
{
    struct stack st;
    st.p = new int[size];
    st.size = size;
    struct stack* stackPointer = &st;
    return stackPointer;

}



void push(struct stack* st, int el) {

    if (st->top == (st->size) - 1) {
        cout << "this operation cannot be done as the size is full :(" << endl;
    }
    else
    {
        st->top = (st->top)  ;
        st->p[st->top] = el;
    }

}

void pop(struct stack* st) {

    if (st->top == -1) 
        cout << "stack is already empty" << endl;
    else
        st->p[st->top] = NULL;
    

}
void displayStack(struct stack* st) {
 
    for (int i = 0; i <= st->top; i  ) {
        cout << st->p[i] << endl;
    }
}
int main()
{
    struct stack* st = createStack(5);
    push(st, 1);
    push(st, 2);
    push(st, 3);
    push(st, 4);
    displayStack(st);
    pop(st);
    displayStack(st);

}

CodePudding user response:

There are a few problems with your code. First, as others have said, you're just doing C code without cout. Instead, you might want stack to look like this:

struct stack {
    stack(int sz);

    void push(int value);
    int pop();

    int top = -1;
    int size = 0;
    int * p = nullptr;
};

std::ostream & operator<<(stack &stack) {
    for (int i = 0; i <= stack->top; i  ) {
        cout << stack->p[i] << endl;
    }
}

stack::stack(int sz)
    : size(sz), p(new int[size])
{
}

void push(int value) {

    if (top == (size) - 1) {
        cout << "this operation cannot be done as the size is full :(" << endl;
    }
    else {
        p[  top] = el;
    }
}

int pop() {
    return top < 0 ? INT_MIN : p[top--];
}

int main() {
    stack st(5);
    st.push(1);
    st.push(2);
    st.push(3);
    st.push(4);

    cout << "First dump: " << st << endl;

    st.pop();
    cout << "Second dump: " << st << endl;

}

CodePudding user response:

At first: You tagged C , but your code is C – apart from not providing void to main, outputting to std::cout and using namespace std – the latter you shouldn't do anyway!

createStack function should be a constructor instead, push and pop should be member functions and you should prevent access to the internal data by making it private. Typically, one would rather use a class than a struct (structs usually are used for POD types). That would look like:

class Stack
{
// default accessibility for class is private, so need to switch to public first
public:
    Stack(size_t capacity)
        : m_capacity(capacity), m_size(0), m_data(new int[capacity])
    { }

    bool push(int value);
    bool pop();
    int top();

// now private section:
private:
    size_t m_capacity;
    size_t m_size;
    //int* m_data;
    // use of a smart pointer avoids necessity to care for memory management manually:
    std::unique_ptr<int[]> m_data;
};

Sure, that looks pretty different now. But that's the C way. If you don't get along with you might want to peek in a good C book.

Some additional changes:

  • I renamed size to capacity, and top to size. Correct data type for specifying object or array sizes is std::size_t (or just size_t), you need to #include <cstddef> for. Note, though, that this type is unsigned (negative sizes are meaningless anyway).
  • Old top/new size has different semantics, not indexing the last element, but holding the number of elements – or index to one past the last element. This is rather typical semantics in C – and actually C as well.
  • The m_ prefix signals the variables being members of a class, it helps distinguishing class members from local variables. Such a convention is not uncommon, but no necessity. Decide you yourself if you want to follow or not...
  • I added a top function returning the last element on the stack. Note that the data and size members are private, so they cannot be accessed from outside the class, thus a user couldn't retrieve the top element without the function.
  • I changed the return types from void to bool – it is a pretty questionable idea to do any output from within a general purpose class. Users of it might want to provide different output, e.g. in another language, and you now are spoiling their programme. In other words: You limit reusability. So let's just return a success indicator and leave the output to the user (you personally would do so within main then).

Of course implementation needs to be changed a little bit, too. You might add the function bodies directly within the class definition (drop the semicolon then), usually you define the class in a header (stack.h or stack.hpp), but the member functions in a separate source file (stack.cpp). The latter would then contain:

#include "stack.h" // should always be the very first include:
                   // implicit check, if the header is self-contained, i.e.
                   // includes all headers it needs for the class definition

bool stack::push(int value)
//        ^^ scope resolution: identifies the push function of class stack
{
    if(m_size == m_capacity)
    {
        return false;
    }
    m_data[m_size  ] = value;
    return true;
}

bool stack::pop()
{
    if(m_size == 0)
    {
        return false;
    }
    --m_size;
    // you don't need to assign another value like 0
    // it would be overwritten with next push anyway
    // 
    // note that NULL would have been wrong anyway, that's for pointers!
    // apart from, you should prefer C   KEYWORDS over obsolete C MACROS,
    // i.e. prefer nullptr over NULL
    //
    // note, too, that you did NOT reduce top on popping in your version
    // should have caused outputting 1234 twice in your test code instead
    // of 1234 and 123 – which I assume you meant by 'not working'
    // – please get used to more precise error descriptions, by the way!

    return true;
}

int top()
{
    return m_data[m_size - 1];
}

Well, top is a pretty basic implementation, it relies on undefined behaviour if the stack is empty (i.e. it is the responsibility of the user to check size first!). Alternatively you could:

  • check the size yourself and throw an exception if the stack is empty
  • change the return type to bool and have a reference argument to provide the top value to (bool top(int& value);) – as being a reference, you indeed can do assignments to.

main would contain code like this one:

    Stack s;
    s.push(1);
//   ^ call class member function; for pointers use ->
    s.push(2);
    std::cout << s.top();
    s.pop();

Finally outputting the entire stack:

Have you noticed that you can write std::cout << 7 << someVariable << std::endl;? What if you could do the same with your stack?

No problem:

class Stack
{
public:
    // see above
private:
    // need to declare a FRIEND so that the function/operator has access to
    // the private class members
    friend std::ostream& operator<<(std::ostream& s, Stack const& s);

    // private members, see above
};

std::ostream& operator<<(std::ostream& s, Stack const& s)
{
    // now do the output to s just as the original displayStack did to std::cout
    // but consider the changed semantics of top/size
    return s;
}

That's it:

Stack s;
std::cout << s << std::endl; // now fine

That's called operator overloading.

EDIT: Considering paddy's comment to the question (didn't notice myself):

Main reason for your original programme failing was returning a local variable from the stack. That variable runs out of scope on leaving the function, though, so accessing it is actually undefined behaviour. What then happens technically is that the stack's contents (top, size and the pointer) likely get overwritten by next function call that reuses the stack. A problem gone away with the new class constructor approach proposed above...

  • Related