I would like to make an rpn calculator and create unit test using nunit for the dictionary to test operations, but i don't know how to make it.
static Stack<double> stack { get; set; } = new Stack<double>();
static Dictionary<string, Action> operators = new Dictionary<string, Action>
{
["+"] = () => { stack.Push(stack.Pop() + stack.Pop()); },
["-"] = () => { var x = stack.Pop(); stack.Push(stack.Pop() - x); },
["*"] = () => { stack.Push(stack.Pop() * stack.Pop()); },
["/"] = () => { var x = stack.Pop(); if (x == 0) throw new DivideByZeroException(); stack.Push(stack.Pop() / x); },
["clr"] = () => { stack.Clear(); },
["!"] = () => { var x = stack.Pop(); stack.Push(x == 0 ? 1 : 0); },
["!="] = () => { stack.Push(stack.Pop() == stack.Pop() ? 0 : 1); },
["%"] = () => { var x = stack.Pop(); stack.Push(stack.Pop() % x); },
["++"] = () => { var x = stack.Pop(); x++; stack.Push(x); },
["--"] = () => { var x = stack.Pop(); x--; stack.Push(x); },
}
EDIT: Executing is like
while (true)
{
Display();
var readLine = Console.ReadLine();
var tokens = readLine.Split(" ").Where(t => t != string.Empty).ToArray();
foreach (var token in tokens)
{
try
{
operators[token].Invoke();
}
catch(KeyNotFoundException)
{
stack.Push(double.Parse(token));
}
}
}
I think you should put stack
and operators
as private
fields in some class
called for example CalculatingService
. after that you should create public
method Calculate(...)
, which will return
calculated value:
public class CalculatingService : ICalculatingService
{
private readonly Stack<double> stack { get; set; }
private readonly Dictionary<string, Func<double>> operators;
public CalculatingService()
{
stack = new Stack<double>();
InitDictionary();
}
public double Calculate(string @operator) =>
operators[@operator].Invoke();
public void ClearData() => stack.Clear();
private void InitDictionary() => operators = new Dictionary<string, Func<double>>
{
["+"] = () => stack.Pop() + stack.Pop(),
["-"] = () => { var x = stack.Pop(); return stack.Pop() - x; },
["*"] = () => stack.Pop() * stack.Pop(),
["/"] = () => { var x = stack.Pop(); if (x == 0) throw new DivideByZeroException(); return stack.Pop() / x; },
["!"] = () => { var x = stack.Pop(); return x == 0 ? 1 : 0; },
["!="] = () => stack.Pop() == stack.Pop() ? 0 : 1,
["%"] = () => { var x = stack.Pop(); return stack.Pop() % x; },
["++"] = () => { var x = stack.Pop(); x++; return x; },
["--"] = () => { var x = stack.Pop(); x--; return x; }
};
}
now you can create test methods for all methods in CalculatingService
. You can test Calculate(...)
by writing x test methods for x operators. I dunno, how do u manage stack
- you have to write additional public
methods in CalculatingService
for stack
management like I wrote ClearData()
.