user2852418
user2852418

Reputation: 377

Stack Push and Pop

I am trying to get my push and pop methods working but can't seem to be able to. With the Push method I think it is something to do with nextfree but I'm not to sure. Also with the Pop method I am not to sure how to do it, I will put the pseudo code I have for it below my actual code. Here is my code:

class Program
{

   private string[] Stack = new string[5];
   int nextFree = 3;

    public Program() 
    {

        Stack = new string[5];

        Stack[0] = "Greg";
        Stack[1] = "Matt";
        Stack[2] = "Jack";
        Stack[3] = "Fred";


    }

    static void Main(string[] args)
    {
        Program prog = new Program();
        do
        {
            prog.DisplayMenu();
        }
        while (true);
    }




    public void DisplayMenu()
    {
        Int32 userInput = 0;

        Console.WriteLine("Linear Stack");
        Console.WriteLine("1: Add to stack");
        Console.WriteLine("2: Delete from stack");
        userInput = Int32.Parse(Console.ReadLine());


        switch (userInput)
        {
            case 1:
                this.Push();
                break;

            case 2:
                this.Pop();
                break;
        }

    }


    public void Push()
    {


        if (nextFree == Stack.Length)
        {
            Console.WriteLine("Stackoverflow, to many elements for the stack");
            Console.ReadLine();
        }
        else
        {
            Console.WriteLine("Please enter a name to be added");
            string userInput = Console.ReadLine();

            nextFree++;
            Stack[nextFree] = userInput;

        }
        this.list();
    }


        public void Pop()
        {
            if (nextFree == -1)
            {
                Console.WriteLine("Stack is empty");
                Console.ReadLine();
            }
            else
            {

                nextFree--;
            }

            this.list();
        }

        public void list()
        {
            foreach (string s in Stack)
            {
                Console.Write(s + " ");
            }

            Console.WriteLine();
        }



  }
}

Pop pseudo code:

If Stack is empty
Then error
Else
Return Stack[TopOfStackPointer]
Decrement TopOfStackPointer
EndIF

UPDATE: The Push method works now with the nextFree being initiated with the value 3.

Upvotes: 3

Views: 22057

Answers (6)

Matt
Matt

Reputation: 27001

Late answer - you can easily implement Push and Pop for C# the same way as you have them in Javascript/TypeScript already: There they are working with arrays. The advantage is that you don't need to care about duplicate values - new elements are just appended to the array.

In C#, you can do it like this (note that there is one difference to JavaScript for Push - I am returning the array instead of just the new length, because I think that makes more sense):

void Main()
{
    T[] Push<T>(ref T[] ar, params T[] items)
    {
        var arLength=ar.Length;
        Array.Resize(ref ar, arLength + items.Length);
        for (int i = arLength, j=0; i < arLength + items.Length; i++, j++)
        {
            ar[i] = items[j];
        }
        return ar;
    }
    T Pop<T>(ref T[] ar) 
    { 
        T item = default(T); 
        if (ar.Length > 0) 
        { 
            var tmp = ar.ToList(); item = tmp.LastOrDefault();              
            Array.Resize(ref ar, ar.Length - 1);
        }; 
        return item; 
    }   

   // Example 1: Create a numeric array
   var arr = new[] { 1, 2, 3, 4 };

   // Push 5, 6, 7 to the end
   Push(ref arr, 5, 6, 7).Dump();

   // Pop the last element (7)
   Pop(ref arr).Dump(); arr.Dump();

   // Example 2: "Stack" array 
   var Stack=new[] {"Greg", "Matt"};
   Push(ref Stack, "Jack", "Fred"); Stack.Dump();
   var elem=Pop(ref Stack); elem.Dump(); Stack.Dump();
}

DotNetFiddle

These functions are generic, you can use it with every type of array.
Usage examples:

var emptyIntArray = new int[0]; // empty array: specify type + length=0
var emptyStrArray = new string[0]; // empty array: specify type + length=0
var arr = new[] { 1, 2, 3, 4 }; // example array. can be strings as well!

Pop:

Pop(ref arr); // removes the item with highest index
var item = Pop(ref arr); // removes the item with highest index, returns it
Pop(ref emptyIntArray); // returns 0 (default for int)
Pop(ref emptyStrArray); // returns null (default for string)

Push:

Push(ref arr, 5); // adds element 5 (increases array size by 1)
Push(ref arr, 6, 7, 8); // adds elements 6, 7, 8 (increases array size by 3)
var newLen = Push(ref arr, 9).Length; // adds element 9, returns new length

Note I am using the ref parameter, because I don't want to waste memory by creating a copy of the entire array. That works by resizing the array. Because of the ref parameter, Push and Pop cannot be extension methods.


Output of the program example:

Dumping object(Int32[])
[1,2,3,4,5,6,7]
Dumping object(Int32)
7
Dumping object(Int32[])
[1,2,3,4,5,6]
Dumping object(String[])
[Greg,Matt,Jack,Fred]
Dumping object(String)
Fred
Dumping object(String[])
[Greg,Matt,Jack]

Upvotes: 0

Gert-Jan
Gert-Jan

Reputation: 1

I like the idea of the MStack class (see Raz Megrelidze's answer). However, the problem with a one dimensional list to implement a stack, is that it cannot handle duplicate values. So in many cases it is a failing stack.

So here is my Dictionary variation, which can handle duplicates.

public class MStack<T> : IEnumerable<T>
{
    private readonly Dictionary<int, T> stack = new Dictionary<int, T>();

    public void Push(T item)
    {
        stack.Add(stack.Count, item);
    }

    public T Pop()
    {
        var item = Peek();
        stack.Remove(stack.Count - 1);
        return item;
    }

    public T Peek()
    {
        return stack[stack.Count - 1];
    }

    public int Count { get { return stack.Count; } }

    public IEnumerator<T> GetEnumerator()
    {
        for (int i = 0; i < stack.Count; i++)
            yield return Peek();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

Upvotes: 0

Rezo Megrelidze
Rezo Megrelidze

Reputation: 3060

Here's my implementation of stack.

public class MStack<T> : IEnumerable<T>
{
    private readonly List<T> stack = new List<T>();

    public void Push(T item)
    {
        stack.Add(item);
    }

    public T Pop()
    {
        var item = Peek();
        stack.Remove(Peek());
        return item;
    }

    public T Peek()
    {
        return stack[stack.Count - 1];
    }

    public int Count { get { return stack.Count; } }

    public IEnumerator<T> GetEnumerator()
    {
        for (int i = 0; i < stack.Count; i++)
            yield return Peek();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

Upvotes: 1

Pierre-Luc Pineault
Pierre-Luc Pineault

Reputation: 9201

Your Pop method is almost complete, the last step you need is to actually remove the value from the array before decrementing the index, to "pop" it out. You can do this by setting the previous value to null.

    public void Pop()
    {
        if (nextFree == -1)
        {
            Console.WriteLine("Stack is empty");
            Console.ReadLine();
        }
        else
        {
            Stack[nextFree] = null;
            nextFree--;
        }

        this.list();
    }

You can also get the value just before to show what have been popped by adding

string value = Stack[nextFree];
Console.WriteLine("Just popped value: " + value);

before setting it to null

It is not necessary here to actually return it like in your pseudocode, since you're not using the value outside. If you need it, consider changing the code to

    public string Pop()
    {
        string value = string.Empty;

        if (nextFree == -1)
        {
            Console.WriteLine("Stack is empty");
            Console.ReadLine();
        }
        else
        {
            value = Stack[nextFree];
            Stack[nextFree] = null;
            nextFree--;
        }

        this.list();
        return value;
    }

Notice the return type also changed from void to string.

Upvotes: 2

peter.petrov
peter.petrov

Reputation: 39457

Try this code. Also make sure to compare with your version to see where your problems were.

        using System;
        using System.Collections.Generic;
        using System.Linq;
        using System.Text;

        namespace ConsoleApplication12
        {
            class Program
            {

                private string[] Stack = new string[5];
                private int nextFree;

                public Program()
                {
                    Stack = new string[10];
                    Stack[0] = "Greg";
                    Stack[1] = "Matt";
                    Stack[2] = "Jack";
                    Stack[3] = "Fred";
                    nextFree = 4;
                }

                static void Main(string[] args)
                {
                    Program prog = new Program();
                    do
                    {
                        prog.DisplayMenu();
                    }
                    while (true);
                }




                public void DisplayMenu()
                {
                    Int32 userInput = 0;

                    Console.WriteLine("Linear Stack");
                    Console.WriteLine("1: Add to stack");
                    Console.WriteLine("2: Delete from stack");
                    String s = Console.ReadLine().Trim();
                    try
                    {
                        userInput = Int32.Parse(s);
                    }
                    catch (Exception)
                    {
                        userInput = 1;
                    }

                    switch (userInput)
                    {
                        case 1:
                            this.Push();
                            break;

                        case 2:
                            this.Pop();
                            break;
                    }

                }


                public void Push()
                {
                    if (nextFree == Stack.Length)
                    {
                        Console.WriteLine("Stackoverflow, to many elements for the stack");
                        Console.ReadLine();
                    }
                    else
                    {
                        Console.WriteLine("Please enter a name to be added");
                        string userInput = Console.ReadLine();
                        Stack[nextFree] = userInput;
                        nextFree++;
                    }
                    this.List();
                }


                public String Pop()
                {
                    if (nextFree == 0)
                    {
                        Console.WriteLine("Stack is empty");
                        return null;
                    }
                    else
                    {
                        String res = Stack[nextFree - 1];
                        nextFree--;
                        this.List();
                        return res;
                    }
                }

                public void List()
                {
                    for (int k = 0; k < nextFree; k++)
                    {
                        Console.Write(this.Stack[k] + " ");
                    }
                    Console.WriteLine();
                }
            }

        }

Upvotes: 2

System Down
System Down

Reputation: 6260

You need to instantiate the value of nextFree to 4 when you first start (since you already have 4 items in your stack).

When checking to see if the value of nextFree is out of bounds of not, you need to remember that array indexes are zero based (i.e. they start at 0). So your condition should be:

if(nextFree >= Stack.Length - 1)

Upvotes: 4

Related Questions