简单的表达式计算及逆波兰栈
今天Boss不在,可以偷偷玩会。想写一个程序计算一个字符串表达式(假定表达式合法),使用逆波兰栈的原理。一开始觉得很容易,写了一会倒也出了不少问题,好在都是些小问题。
1.在字符串拆分那块就琢磨半天,也没想出什么好方法,最后用很土的方法实现的(方法StringSplit)
2.发现老是要判断符号栈是否有元素,干脆先压入一个“$”(operStack.Push("$")),类似“哨兵”。
3.遇到类似“-15*2+3*(1+2)”这样的式子时出错,所以在数字栈中先压入0(numStack.Push(0))
4.为了在扫描字符串结束后自动弹出符号栈中的符号并计算,在原字符末加上“$”,让程序在遇“$”时弹出所有符号。
程序如下,错误的或都不好的地方大家多多批评,感谢:
private static Regex regOper = new Regex(@"[\+\-\*/\(\)$]");
static void Main(string[] args)
{
string expression = Console.ReadLine();
Stack<double> numStack = new Stack<double>();
Stack<string> operStack = new Stack<string>();
numStack.Push(0);
operStack.Push("$");
List<string> list = StringSplit(expression);
string oper = "";
foreach (string element in list)
{
if (regOper.IsMatch(element))
{
switch (element)
{
case "+":
case "-":
while ((oper = operStack.Pop()) != "$" && oper != "(")
{
double temp = Cal(numStack.Pop(), numStack.Pop(), oper);
numStack.Push(temp);
}
operStack.Push(oper);
operStack.Push(element);
break;
case "*":
case "/":
while ((oper = operStack.Pop()) == "*" || oper == "/")
{
double temp = Cal(numStack.Pop(), numStack.Pop(), oper);
numStack.Push(temp);
}
operStack.Push(oper);
operStack.Push(element);
break;
case "(":
operStack.Push(element);
break;
case ")":
while ((oper = operStack.Pop()) != "(")
{
double temp = Cal(numStack.Pop(), numStack.Pop(), oper);
numStack.Push(temp);
}
break;
default:
while ((oper = operStack.Pop()) != "$")
{
double temp = Cal(numStack.Pop(), numStack.Pop(), oper);
numStack.Push(temp);
}
break;
}
}
else
{
numStack.Push(Convert.ToDouble(element));
}
}
Console.WriteLine("表达式结果:" + numStack.Pop());
Console.Read();
}
//拆分表达式
static List<string> StringSplit(string s)
{
List<string> list = new List<string>();
int position = -1;
s += "$";
for (int i = 0; i < s.Length; i++)
{
if (regOper.IsMatch(s[i].ToString()))
{
if (i - position > 1)
{
list.Add(s.Substring(position + 1, i - position - 1));
}
list.Add(s.Substring(i, 1));
position = i;
}
}
return list;
}
//计算两个数值的运算结果
static double Cal(double num1, double num2, string oper)
{
switch (oper)
{
case "+":
return num2 + num1;
case "-":
return num2 - num1;
case "*":
return num2 * num1;
case "/":
return num2 / num1;
default:
return 0;
}
}
static void Main(string[] args)
{
string expression = Console.ReadLine();
Stack<double> numStack = new Stack<double>();
Stack<string> operStack = new Stack<string>();
numStack.Push(0);
operStack.Push("$");
List<string> list = StringSplit(expression);
string oper = "";
foreach (string element in list)
{
if (regOper.IsMatch(element))
{
switch (element)
{
case "+":
case "-":
while ((oper = operStack.Pop()) != "$" && oper != "(")
{
double temp = Cal(numStack.Pop(), numStack.Pop(), oper);
numStack.Push(temp);
}
operStack.Push(oper);
operStack.Push(element);
break;
case "*":
case "/":
while ((oper = operStack.Pop()) == "*" || oper == "/")
{
double temp = Cal(numStack.Pop(), numStack.Pop(), oper);
numStack.Push(temp);
}
operStack.Push(oper);
operStack.Push(element);
break;
case "(":
operStack.Push(element);
break;
case ")":
while ((oper = operStack.Pop()) != "(")
{
double temp = Cal(numStack.Pop(), numStack.Pop(), oper);
numStack.Push(temp);
}
break;
default:
while ((oper = operStack.Pop()) != "$")
{
double temp = Cal(numStack.Pop(), numStack.Pop(), oper);
numStack.Push(temp);
}
break;
}
}
else
{
numStack.Push(Convert.ToDouble(element));
}
}
Console.WriteLine("表达式结果:" + numStack.Pop());
Console.Read();
}
//拆分表达式
static List<string> StringSplit(string s)
{
List<string> list = new List<string>();
int position = -1;
s += "$";
for (int i = 0; i < s.Length; i++)
{
if (regOper.IsMatch(s[i].ToString()))
{
if (i - position > 1)
{
list.Add(s.Substring(position + 1, i - position - 1));
}
list.Add(s.Substring(i, 1));
position = i;
}
}
return list;
}
//计算两个数值的运算结果
static double Cal(double num1, double num2, string oper)
{
switch (oper)
{
case "+":
return num2 + num1;
case "-":
return num2 - num1;
case "*":
return num2 * num1;
case "/":
return num2 / num1;
default:
return 0;
}
}