How to use a Stack's Pop method in another method - c#

I am attempting to write a program for an assignment that Pops and adds the first 2 items in a Stack. The program has a Pop method, but I would like to know how to call the method within the Add method. This Add is supposed to Pop the top two items in a stack, get their sum, and Push that sum to the stack. In my code below I call the Pop method twice inside the Add method, but when I display the stack, the stack still has all of the original values. Is there something more/else I need to go to get the Pop method to work?
class StackEmptyException : ApplicationException
{
public StackEmptyException(String message) : base(message)
{
}
}
class MathStack
{
private int[] dataStack;
private int size;
private int top = -1;
public bool IsEmpty()
{
return top == -1;
}
public bool IsFull()
{
return top == size - 1;
}
public void Push(int i)
{
dataStack[++top] = i;
}
public int Pop()
{
if (IsEmpty())
throw new StackEmptyException
("Stack empty -- cannot pop");
else
return dataStack[top--];
}
public int Top()
{
if (IsEmpty())
throw new StackEmptyException
("Stack empty -- top undefined");
else
return dataStack[top];
}
public MathStack()
{
dataStack = new int[10];
}
public MathStack(int s)
{
size = 10;
dataStack = new int[size];
}
public void LoadStack(int v)
{
dataStack[++top] = v;
}
public void Display()
{
int[] display = new int[dataStack.Length];
for (int i = 0; i < dataStack.Length; i++)
{
display[i] = dataStack[i];
Console.WriteLine("{0}", display[i]);
}
}
public void Add()
{
int add1 = dataStack[0];
int add2 = dataStack[1];
Pop();
Pop();
int sum = add1 + add2;
Console.WriteLine("Sum: {0}", sum);
}
}
class Program
{
static void Main(string[] args)
{
MathStack stack1 = new MathStack();
stack1.Push(9);
stack1.Push(8);
stack1.Push(7);
stack1.Push(6);
stack1.Push(5);
stack1.Push(4);
stack1.Push(3);
stack1.Push(2);
stack1.Push(1);
stack1.Push(0);
stack1.Display();
stack1.Add();
stack1.Display();
Console.ReadLine();
}
}

There are two things wrong with your code.
First, the Display method displays the whole array. Except that since you're not physically removing the items from the array, you need to stop at the index top:
public void Display()
{
if (IsEmpty())
{
Console.WriteLine("Empty");
return;
}
for (int i = 0; i <= top; i++)
{
Console.WriteLine(dataStack[i]);
}
}
The second issue is your Add. From what I understand, you want to pop the last two items, sum them, and push the result. In your implementation, you are actually summing the first two items (not the last two). A better version would be:
public void Add()
{
int add1 = Pop();
int add2 = Pop();
int sum = add1 + add2;
Console.WriteLine("Sum: {0}", sum);
Push(sum);
}
Notice how I do not directly access dataStack. If your API is correctly implemented, it should not be needed.

Related

How to fix this ISeries interface implementation in Class1?

I am developing a series of numbers starting from Setstart(2) function from ISeries interface. I tried to implement this interface in Class1 but it threw an error to me. And I am getting stuck at this error and not been able to figure out to fix this. What am I missing? Please help
I tried to make all functions in the interface public
I tried to remove public access specifier from interface
public interface ISeries {
void Setstart (int a);
int GetNext ();
void Reset ();
}
class Class1 : ISeries {
int val;
void Setstart (int a) {
val = a;
}
int GetNext () {
return val++;
}
void Reset () {
val = 0;
}
static void Main () {
Class1 c = new Class1 ();
c.Setstart (2);
Console.WriteLine (c.GetNext ());
c.Reset ();
Console.WriteLine ();
}
}
I expect the output to be 3 and 0 error is being generated
Your should try something like this.
Because you have to play with one variable so you have to make use of ref `keyword in this case.
and also you have to mark all the method inside a class as a public otherwise you were not be able to access those method inside main
Code:
using System;
namespace StackoverflowProblem
{
public interface ISeries
{
void Setstart(ref int value);
int GetNext(ref int value);
void Reset(ref int value);
}
public class Class1 : ISeries
{
public int val { get; set; }
public void Setstart(ref int value)
{
this.val = value;
}
public int GetNext(ref int value)
{
value = value + 1;
this.val = value;
return this.val;
}
public void Reset(ref int value)
{
// Resetting val.
value = 0;
this.val = value;
}
}
class Program
{
static void Main(string[] args)
{
Class1 c = new Class1();
int value = 2;
c.Setstart(ref value);
Console.WriteLine(" " + c.GetNext(ref value));
c.Reset(ref value);
Console.WriteLine();
}
}
}
Output:
val++ will incriment after returning the current value, ++val will increment first then return the value, you should now get 3, also make it proper scoped to access the methods from outside
class Class1 : ISeries {
int val;
public void Setstart (int a) {
val = a;
}
public int GetNext () {
return ++val;
}
public void Reset () {
val = 0;
}
static void Main () {
Class1 c = new Class1();
c.Setstart(2);
Console.WriteLine (c.GetNext());
c.Reset();
Console.WriteLine ("");
}
}
You need to make your methods public to be accessible outside from class which is missing other than that your code looks fine.
You need to make all the 3 methods public as per your scenario like :
public void Setstart (int a) {
and you will need to first add 1 and then return to get 3 as output as val++ will return the current value and then increment it by 1:
public int GetNext () {
// return val++; // Post increment will not work according to question.
val = val + 1;
return val;
}
Your class with complete implementation of Interface would be like following:
public class Class1 : ISeries {
int val;
public void Setstart (int a) {
val = a;
}
public int GetNext () {
val = val + 1;
return val;
}
public void Reset () {
val = 0;
}
}

How can I populate a string array with a parameter method C#

I am trying to populate a string array called "items" with a pre written method called "insert".
The project has pre written code "b.insert("apple");" etc etc and the method given is "public void insert(T item)". I have to write the code in this method to make the "insert" function work. I have to pass "item" into "items" array but my for loop simply gives me the output "milk" 10 times. Because of this, I know that "item" value is simply changing to the last string passed in the insert method. Would I have to write a nested for loop where "item" is a counter? In this case "item" cannot be a counter because it is a string type. Should I convert "item" into an array?
I'm not sure why such a seemingly simple task has me stumped by I've been at it for hours and at this point I just want to sort it out for the sake of sanity.
thanks in advance
class Program
{
static void Main(string[] args)
{
BoundedBag<string> b = new BoundedBag<string>("ShoppingList", 10);
b.insert("apple");
b.insert("eggs");
b.insert("milk");
Console.WriteLine(b);
Console.ReadKey();
}
}
public interface Bag<T> where T : class
{
void insert(T item);
string getName();
bool isEmpty();
}
public class BoundedBag<T> : Bag<T> where T : class
{
private string bagName; // the name of the bag
protected int size; // max size of the bag
private int lastIndex;
protected T[] items;
public BoundedBag(string name, int size)
{
bagName = name;
this.size = size;
rnd = new Random();
items = new T[size];
}
public string getName()
{
return bagName;
}
public bool isEmpty()
{
return lastIndex == -1;
}
public bool isFull()
{
if(items.Length >= size)
{
return true;
}
else { return false;}
}
public void insert(T item)
{
// fill in the code as directed below:
// insert item into items container
// throws FullBagException if necessary
for (int i = 0; i < size; i++)
{
items[i] = item;
}
}
}
You only want to insert one item into your array on insert so you shouldn't have a loop at all. Use the lastIndex field to insert one item into the appropriate place in the array:
public void insert(T item)
{
// fill in the code as directed below:
// insert item into items container
// throws FullBagException if necessary
if(isFull())
{
throw new FullBagException();
}
items[++lastIndex] = item;
}
Unfortunately your isFull method is also broken and your isEmpty method won't work properly unless you change the constructor.
public BoundedBag(string name, int size)
{
bagName = name;
this.size = size;
items = new T[size];
lastIndex = -1;
}
public bool isFull()
{
return lastIndex == size - 1;
}

Can't Call arrays in main method

I'm practicing methods, but the problem is I want to separate inputting and sorting, the display method will be the main, I'm having trouble fixing this calling from other class.
This is my script :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CaseProblem
{
class Method
{
static void MethodInput()
{
int[] array = new int[5];
int i;
// loop for accepting values in array
for (i = 0; i < 5; i++)
{
Console.Write("Enter number:\t");
array[i] = int.Parse(Console.ReadLine());
}
}
public static void MethodSort()
{
foreach (int i in array)
{
Console.Write(" {0}", i);
}
}
}
class Program
{
static void Main(int[]array)
{
//sorting array value;
Array.Sort(array); //use array's sort function
Method.MethodSort(array);
Console.ReadLine();
}
}
}
Thank you for your help
First of all Main() ( or "EntryPoint" as we should call it ) cannot have int[] as an input parameter but string[] instead you should learn basics of programming before starting to actually code something.
Second thing :
I want to separate inputting and sorting
You can create an object called Input
public class Input
{
public static void Write(string message)
{
Console.WriteLine(message);
}
public static int? ReadInt(string reason)
{
Write(reason);
string userInput = Console.ReadLine();
int parsed = 0;
if(int.TryParse(userInput, out parsed))
return (int?)parsed;
return null;
}
}
This will be your "InputLogic" which you can use as Input.ReadInt("Please specify your age: ");
Next you can make an Operations object :
public class Operations
{
public void Display(int[] arr)
{
foreach(int i in arr)
{
// and since you have "Input" class that can display things
Input.Write(i.ToString());
}
}
public void Sort(ref int[] arr)
{
Array.Sort(arr);
}
}
Now the last thing is to combine it within your Program
class Program
{
static void Main(string[] args)
{
int[] arr = new int[5];
for(int i = 0; i < arr.Length; i++)
{
int? input = null;
while( !( input = Input.ReadInt("Give me number") ).HasValue ) { }
arr[i] = input.Value;
}
Operations op = new Operations();
op.Display(arr);
op.Sort(ref arr);
op.Display(arr);
}
}
Well, you are missing the parameter for the called function.
public static void MethodSort(int[] array)
{
foreach (int i in array)
{
Console.Write(" {0}", i);
}
}
note: not tested
Okay, you have two errors, both in this method:
public static void MethodSort()
{
foreach (int i in array)
{
Console.Write(" {0}", i);
}
}
as well as how you call it:
Method.MethodSort(array);
The first problem is that the method uses the variable array, which doesn't exist in that method's scope.
The second problem is that you are passing array to the call to Method.MethodSort, but that method isn't configured to take a parameter.
There are two ways to approach solving this: remove array entirely, or change the method to accept it. Now, you obviously cannot remove array, as the whole point is to do stuff with it. Therefore, the logical solution is to add array as a parameter to your method:
public static void MethodSort(int[] array)
{
foreach (int i in array)
{
Console.Write(" {0}", i);
}
}

Make Length property available for my class C#

I want to create class Massive and to add a method for adding two massives. But property Length for my class instances doesn't work.
public static void Add(Massiv mas1, Massiv mas2, ref Massiv mas3)
{
if (mas1.Length != mas2.Length)
{
Console.WriteLine("Error!"); return;
}
for (int i = 0; i < mas.Length; ++i)
{
mas3[i] = mas1[i] + mas2[i];
}
}
How to make it available for my class?
It's my code.
class Massiv
{
public Massiv(int n)
{
mas = new int[n];
Random rand = new Random();
for (int i = 0; i < mas.Length; ++i)
{
mas[i] = rand.Next(0, 10);
}
}
public void ShowAll()
{
Console.WriteLine("Massive: ");
foreach (var elem in mas)
{
Console.Write(elem + " ");
}
Console.WriteLine();
}
public void ShowElement(int index)
{
try
{
Console.WriteLine("mas[{0}] = {1}", index, mas[index]);
}
catch (IndexOutOfRangeException)
{
Console.WriteLine("Error!");
}
}
public static void Add(Massiv mas1, Massiv mas2, ref Massiv mas3)
{
if (mas1.Length != mas2.Length)
{
Console.WriteLine("Error!"); return;
}
for (int i = 0; i < mas.Length; ++i)
{
mas3[i] = mas1[i] + mas2[i];
}
}
public int this[int index]
{
get { return mas[index]; }
set { mas[index] = value; }
}
private int[] mas;
}
}
It seems like you have not declared any Length property, therefore, the compiler cannot possibly know one.
Basically, add this to your class:
public int Length {
get {
}
set {
}
}
In the getter, you need to return the value of the property, while in the setter, you will have to change it.
In this case, you seem to want to retrieve the length of your internal array. If you do not need write-access, you can skip the set part:
public int Length {
get {
return mas.Length;
}
}
Just add this property to your class:
public int Length {
get { return mas.Length; }
}
Note it has only a get accessor, which makes it read only (You don't seem to need write access since you initialize the private array in the constructor).
public int Length {
get {
return mas.Length;
}
}

A robust method of tracking failed workers with ThreadPool

I'm looking for a good method of tracking (counting) which workers have failed when queued with a Threadpool and using WaitHandle.WaitAll() for all threads to finish.
Is Interlocking a counter a good technique or is there a more robust strategy?
Okay, here's an approach that you could take. I've encapsulated the data that we want to track into a class TrackedWorkers. There is a constructor on this class that enables you to set how many workers will be working. Then, the workers are launched using LaunchWorkers which requires a delegate that eats an object and returns a bool. The object represents the input to the worker and the bool represents success or failure depending on true or false being the return value, respectively.
So basically what we do we have an array to track worker state. We launch the workers and set the status corresponding to that worker depending on the return value from the worker. When the worker returns, we set an AutoResetEvent and WaitHandle.WaitAll for all the AutoResetEvents to be set.
Note that there is an nested class to track the work (the delegate) the worker is supposed to do, the input to that work, and an ID used to set the status AutoResetEvent corresponding to that thread.
Note very carefully that once the work is done we are not holding a reference to the work delegate func nor to the input. This is important so that we don't accidentally prevent stuff from being garbage collected.
There are methods for getting the status of a particular worker, as well as all the indexes of the workers that succeeded and all the indexes of the workers that failed.
One last note: I do not consider this code production ready. It is merely a sketch of the approach that I would take. You need to take care to add testing, exception handling and other such details.
class TrackedWorkers {
class WorkerState {
public object Input { get; private set; }
public int ID { get; private set; }
public Func<object, bool> Func { get; private set; }
public WorkerState(Func<object, bool> func, object input, int id) {
Func = func;
Input = input;
ID = id;
}
}
AutoResetEvent[] events;
bool[] statuses;
bool _workComplete;
int _number;
public TrackedWorkers(int number) {
if (number <= 0 || number > 64) {
throw new ArgumentOutOfRangeException(
"number",
"number must be positive and at most 64"
);
}
this._number = number;
events = new AutoResetEvent[number];
statuses = new bool[number];
_workComplete = false;
}
void Initialize() {
_workComplete = false;
for (int i = 0; i < _number; i++) {
events[i] = new AutoResetEvent(false);
statuses[i] = true;
}
}
void DoWork(object state) {
WorkerState ws = (WorkerState)state;
statuses[ws.ID] = ws.Func(ws.Input);
events[ws.ID].Set();
}
public void LaunchWorkers(Func<object, bool> func, object[] inputs) {
Initialize();
for (int i = 0; i < _number; i++) {
WorkerState ws = new WorkerState(func, inputs[i], i);
ThreadPool.QueueUserWorkItem(this.DoWork, ws);
}
WaitHandle.WaitAll(events);
_workComplete = true;
}
void ThrowIfWorkIsNotDone() {
if (!_workComplete) {
throw new InvalidOperationException("work not complete");
}
}
public bool GetWorkerStatus(int i) {
ThrowIfWorkIsNotDone();
return statuses[i];
}
public IEnumerable<int> SuccessfulWorkers {
get {
return WorkersWhere(b => b);
}
}
public IEnumerable<int> FailedWorkers {
get {
return WorkersWhere(b => !b);
}
}
IEnumerable<int> WorkersWhere(Predicate<bool> predicate) {
ThrowIfWorkIsNotDone();
for (int i = 0; i < _number; i++) {
if (predicate(statuses[i])) {
yield return i;
}
}
}
}
Sample usage:
class Program {
static Random rg = new Random();
static object lockObject = new object();
static void Main(string[] args) {
int count = 64;
Pair[] pairs = new Pair[count];
for(int i = 0; i < count; i++) {
pairs[i] = new Pair(i, 2 * i);
}
TrackedWorkers workers = new TrackedWorkers(count);
workers.LaunchWorkers(SleepAndAdd, pairs.Cast<object>().ToArray());
Console.WriteLine(
"Number successful: {0}",
workers.SuccessfulWorkers.Count()
);
Console.WriteLine(
"Number failed: {0}",
workers.FailedWorkers.Count()
);
}
static bool SleepAndAdd(object o) {
Pair pair = (Pair)o;
int timeout;
double d;
lock (lockObject) {
timeout = rg.Next(1000);
d = rg.NextDouble();
}
Thread.Sleep(timeout);
bool success = d < 0.5;
if (success) {
Console.WriteLine(pair.First + pair.Second);
}
return (success);
}
}
The above program is going to launch sixty-four threads. The ith thread has the task of adding the numbers i and 2 * i and printing the result to the console. However, I have added a random amount of sleep (less than one second) to simulate busyness and I flip a coin to determine success or failure of the thread. Those that succeed print the sum they were tasked with and return true. Those that fail print nothing and return false.
Here I have used
struct Pair {
public int First { get; private set; }
public int Second { get; private set; }
public Pair(int first, int second) : this() {
this.First = first;
this.Second = second;
}
}

Categories

Resources