将 char(又名:'+')转换为运算符
Converting a char (aka: '+') to an operator
我给自己设定了 RPN 计算器的挑战。我有一个包含所用数字的列表(按顺序)和另一个包含所用运算符的列表(按顺序,作为字符)。我如何创建一个函数,它将从 list1 中获取 [0],从 list2 中获取 [0],然后从 list1 中获取 [1],然后从 list2 中获取 [1]... 但是当从 list2 中获取值作为 char 时,将其转换为可用于计算的实际运算符? - 谢谢
static int cal()
{
string[] store = input.Split(' ');
List<int> num = new List<int>();
List<char> op = new List<char>();
foreach (string i in store)
{
if (Convert.ToInt32(i) / Convert.ToInt32(i) == 1)
{
num.Add(Convert.ToInt32(i));
}
else
{
op.Add(Convert.ToChar(i));
}
}
}
您的方法永远行不通,因为 RPN 计算器依赖于基于堆栈的处理。如果您正确实施该部分,其余部分将自行解决。一个简单的 RPN 计算器的伪代码是:
foreach(item in expression)
{
if(isNumber(item))
stack.push(item.toNumber());
else if(item == '+')
stack.push(stack.pop() + stack.pop());
else if(item == '-')
stack.push(stack.pop() - stack.pop());
else
throw Exception("Unknown operator: " + item);
}
if(stack.size != 1)
throw Exception("Expression was invalid");
print("Result is " + stack.pop());
如果您像这样实现它而不是 2 个单独的列表,其余的将随之而来。
首先,这种计算器可能适合Stack作为数据存储。
var theStack = new Stack<decimal>();
然后,如果你想从简单的开始,创建一个委托来表示二进制操作(例如,对堆栈顶部 2 个数字的操作)
delegate decimal BinaryOperation(decimal a, decimal b);
您可以创建方法来实现它;
public decimal AddFn(decimal a, decimal b)
{
return a+b;
}
然后创建字典以在运算符名称和运算符函数之间进行映射;
var map = new Dictionary<string, BinaryOperation>();
map.Add("+", AddFn);
最后,在运行程序中使用地图;
foreach(var i in store)
{
decimal number;
BinaryOperation op;
if (decimal.TryParse(i, out number))
{
// we've found a number
theStack.Push(number);
}
else if (map.TryGetValue(i, out op))
{
// we've found a known operator;
var a = theStack.Pop();
var b = theStack.Pop();
var result = op(a,b);
theStack.Push(result);
}
else
{
throw new Exception("syntax error");
}
}
因此,您可以使用 map
变量注册更多运算符,而无需更改压入、弹出和操作堆栈上的值的核心逻辑。
我猜,你的冷方法看起来像这样:
static int cal()
{
string[] store = input.Split(' ');
var res = 0;
int value;
var mapOp = new Dictionary<string, Func<List<int>, int>>();
mapOp.Add("+", l => l.Aggregate(0, (x, y) => x + y));
mapOp.Add("-", l => l.Skip(1).Aggregate(l[0], (x, y) => x - y));
var process = new Action<string,List<int>>((o, l) =>
{
var operation = mapOp[o];
var result = operation(l);
l.Clear();
l.Add(result);
});
var numbers = new List<int>();
foreach (var i in store)
{
if (int.TryParse(i, out value))
numbers.Add(value);
else
process(i, numbers);
}
return numbers.First();
}
我给自己设定了 RPN 计算器的挑战。我有一个包含所用数字的列表(按顺序)和另一个包含所用运算符的列表(按顺序,作为字符)。我如何创建一个函数,它将从 list1 中获取 [0],从 list2 中获取 [0],然后从 list1 中获取 [1],然后从 list2 中获取 [1]... 但是当从 list2 中获取值作为 char 时,将其转换为可用于计算的实际运算符? - 谢谢
static int cal()
{
string[] store = input.Split(' ');
List<int> num = new List<int>();
List<char> op = new List<char>();
foreach (string i in store)
{
if (Convert.ToInt32(i) / Convert.ToInt32(i) == 1)
{
num.Add(Convert.ToInt32(i));
}
else
{
op.Add(Convert.ToChar(i));
}
}
}
您的方法永远行不通,因为 RPN 计算器依赖于基于堆栈的处理。如果您正确实施该部分,其余部分将自行解决。一个简单的 RPN 计算器的伪代码是:
foreach(item in expression)
{
if(isNumber(item))
stack.push(item.toNumber());
else if(item == '+')
stack.push(stack.pop() + stack.pop());
else if(item == '-')
stack.push(stack.pop() - stack.pop());
else
throw Exception("Unknown operator: " + item);
}
if(stack.size != 1)
throw Exception("Expression was invalid");
print("Result is " + stack.pop());
如果您像这样实现它而不是 2 个单独的列表,其余的将随之而来。
首先,这种计算器可能适合Stack作为数据存储。
var theStack = new Stack<decimal>();
然后,如果你想从简单的开始,创建一个委托来表示二进制操作(例如,对堆栈顶部 2 个数字的操作)
delegate decimal BinaryOperation(decimal a, decimal b);
您可以创建方法来实现它;
public decimal AddFn(decimal a, decimal b)
{
return a+b;
}
然后创建字典以在运算符名称和运算符函数之间进行映射;
var map = new Dictionary<string, BinaryOperation>();
map.Add("+", AddFn);
最后,在运行程序中使用地图;
foreach(var i in store)
{
decimal number;
BinaryOperation op;
if (decimal.TryParse(i, out number))
{
// we've found a number
theStack.Push(number);
}
else if (map.TryGetValue(i, out op))
{
// we've found a known operator;
var a = theStack.Pop();
var b = theStack.Pop();
var result = op(a,b);
theStack.Push(result);
}
else
{
throw new Exception("syntax error");
}
}
因此,您可以使用 map
变量注册更多运算符,而无需更改压入、弹出和操作堆栈上的值的核心逻辑。
我猜,你的冷方法看起来像这样:
static int cal()
{
string[] store = input.Split(' ');
var res = 0;
int value;
var mapOp = new Dictionary<string, Func<List<int>, int>>();
mapOp.Add("+", l => l.Aggregate(0, (x, y) => x + y));
mapOp.Add("-", l => l.Skip(1).Aggregate(l[0], (x, y) => x - y));
var process = new Action<string,List<int>>((o, l) =>
{
var operation = mapOp[o];
var result = operation(l);
l.Clear();
l.Add(result);
});
var numbers = new List<int>();
foreach (var i in store)
{
if (int.TryParse(i, out value))
numbers.Add(value);
else
process(i, numbers);
}
return numbers.First();
}