求C#词法分析程序,在线等 目前我有个需求,要求取得给定字符串计算后的数值。如 "20+3*5-10/2.5" 将返回 31表达式中可能出现的运算符号包括 + - × /暂不考虑括号及符号还有其它特殊运算符,但会有小数 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 private const char EndChar = ';'; private const char Inter_Minus = '#';//内部负号 private const char FlagChar = '$'; private static readonly char[] InvalidChars = new char[] {EndChar, Inter_Minus, FlagChar}; private static readonly char[] Symbols = new char[] {'*','/','+','-','(',')'}; private static readonly char[] Symbols_Simple = new char[] {'*','/','+','-',EndChar};public static double EvaluateSimpleExpression(string expression) { double result = 0;//结果 double data = 0;//中间结果 string dataStr; char opera,topopera; int index; ArrayList NS = new ArrayList(); //数栈 ArrayList OS = new ArrayList(); //运算符栈 expression += EndChar; if (expression[0] == '-' || expression[0] == '+') expression = "0" + expression; while ((index = expression.IndexOfAny(Symbols_Simple)) != -1) { if(index != 0) //数据 { try { dataStr = expression.Substring(0,index); if (dataStr[0] == Inter_Minus) dataStr = "-"+dataStr.Remove(0, 1); data = double.Parse(dataStr); NS.Add(data); expression = expression.Substring(index,expression.Length-index); } catch (Exception ec) { throw new Exception("表达式中有不能识别的字符。", ec); } } else //运算符 { try { opera = expression[index]; if (OS.Count == 0) { if (opera == EndChar) result = (double)NS[NS.Count-1]; else OS.Add(opera); } else { topopera = (char)OS[OS.Count-1]; while ((topopera == '*' || topopera == '/') || ((topopera == '+' || topopera == '-') && (opera != '*' && opera != '/')) || (opera == EndChar && topopera != FlagChar)) //当前运算符优先级低于栈顶运算符优先级 { switch (topopera) { case '+': data = (double)NS[NS.Count-2] + (double)NS[NS.Count-1]; break; case '-': data = (double)NS[NS.Count-2] - (double)NS[NS.Count-1]; break; case '*': data = (double)NS[NS.Count-2] * (double)NS[NS.Count-1]; break; case '/': data = (double)NS[NS.Count-2] / (double)NS[NS.Count-1]; break; } NS.RemoveAt(NS.Count-1); NS.RemoveAt(NS.Count-1); NS.Add(data); OS.RemoveAt(OS.Count-1); if (OS.Count == 0) topopera = FlagChar; else topopera = (char)OS[OS.Count-1]; } if (opera == EndChar) { result = (double)NS[NS.Count-1]; } else { OS.Add(opera); } } expression = expression.Substring(index+1,expression.Length-index-1); } catch (Exception ec) { throw new Exception("非法的表达式。", ec); } } } return result; } 首先需要分词,比如+,-都是一个词.将数字也可以分出来,20+3*5-10/2.5分为"20" , "+" , "3" , "*" , "5" , "-" , "10" , "/" , 2.5然后进行语法分析.使用二个堆栈,一个数值,一个是操作符.操作符需要定义优先级.读入数字时将数字push到数字堆栈,读入符号时先将高于操作符的优先级重新计算出数值.并压入数值堆栈中.依上例读入20 数值堆栈为20 操作符堆栈为空读入+ 数值堆栈为20 操作符堆栈为+读入3 数值堆栈为20 3 操作符堆栈为+读入* 数值堆栈为20 3 操作符堆栈为+ *读入5 数值堆栈为20 3 5 操作符堆栈为 + *读入- 由于+ *的优先级高于或者等于-,所以将3*5计算出15放入堆栈中.然后计算20+15得出35放回堆栈中,数值堆栈为35 操作符堆栈为空.这种方式要加入括号也很简单.还有更好的方式就是下一个类似于yacc的东东.很容易实现这个功能的. 使用stack来处理。将表达式改写成后缀式表达式:(2+3)*2 --> 23+2* 用数组保存从数据库中选择单选题的键值这样做对吗?(红色代码部分)如果不对应该怎样保存? 讨化一下:泛型接口为逆变 (打擂台专区)怎么实现当当网首页的无刷新倒计时? 初学windows服务,简单问题盼高人指点~~~~~~~~~~~~~~ 如何使EXCEL格式转换为DBF格式 高手请进 点击事件中更改当前控件属性 在ListBoxItem的Style中无法设置Foreground c#+sqlserver2000开发一个小软件,给钱的……急急急急 委托是咋回事?把我给搞糊了(俺是新手) 字符串如何转化为16进制 一个程序可以有多个进程吗?使用多进程有什么必要?如何强制程序在多进程中运行?
private const char Inter_Minus = '#';//内部负号
private const char FlagChar = '$';
private static readonly char[] InvalidChars = new char[] {EndChar, Inter_Minus, FlagChar};
private static readonly char[] Symbols = new char[] {'*','/','+','-','(',')'};
private static readonly char[] Symbols_Simple = new char[] {'*','/','+','-',EndChar};public static double EvaluateSimpleExpression(string expression)
{
double result = 0;//结果
double data = 0;//中间结果
string dataStr;
char opera,topopera;
int index;
ArrayList NS = new ArrayList(); //数栈
ArrayList OS = new ArrayList(); //运算符栈 expression += EndChar;
if (expression[0] == '-' || expression[0] == '+')
expression = "0" + expression; while ((index = expression.IndexOfAny(Symbols_Simple)) != -1)
{
if(index != 0) //数据
{
try
{
dataStr = expression.Substring(0,index);
if (dataStr[0] == Inter_Minus) dataStr = "-"+dataStr.Remove(0, 1);
data = double.Parse(dataStr);
NS.Add(data);
expression = expression.Substring(index,expression.Length-index);
}
catch (Exception ec)
{
throw new Exception("表达式中有不能识别的字符。", ec);
}
}
else //运算符
{
try
{
opera = expression[index];
if (OS.Count == 0)
{
if (opera == EndChar)
result = (double)NS[NS.Count-1];
else
OS.Add(opera);
}
else
{
topopera = (char)OS[OS.Count-1];
while ((topopera == '*' || topopera == '/') ||
((topopera == '+' || topopera == '-') && (opera != '*' && opera != '/')) ||
(opera == EndChar && topopera != FlagChar))
//当前运算符优先级低于栈顶运算符优先级
{
switch (topopera)
{
case '+':
data = (double)NS[NS.Count-2] + (double)NS[NS.Count-1];
break;
case '-':
data = (double)NS[NS.Count-2] - (double)NS[NS.Count-1];
break;
case '*':
data = (double)NS[NS.Count-2] * (double)NS[NS.Count-1];
break;
case '/':
data = (double)NS[NS.Count-2] / (double)NS[NS.Count-1];
break;
}
NS.RemoveAt(NS.Count-1);
NS.RemoveAt(NS.Count-1);
NS.Add(data);
OS.RemoveAt(OS.Count-1);
if (OS.Count == 0)
topopera = FlagChar;
else
topopera = (char)OS[OS.Count-1];
}
if (opera == EndChar)
{
result = (double)NS[NS.Count-1];
}
else
{
OS.Add(opera);
}
}
expression = expression.Substring(index+1,expression.Length-index-1);
}
catch (Exception ec)
{
throw new Exception("非法的表达式。", ec);
}
}
}
return result;
}
20+3*5-10/2.5分为
"20" , "+" , "3" , "*" , "5" , "-" , "10" , "/" , 2.5然后进行语法分析.使用二个堆栈,一个数值,一个是操作符.操作符需要定义优先级.
读入数字时将数字push到数字堆栈,读入符号时先将高于操作符的优先级重新计算出数值.并压入数值堆栈中.依上例
读入20 数值堆栈为20 操作符堆栈为空
读入+ 数值堆栈为20 操作符堆栈为+
读入3 数值堆栈为20 3 操作符堆栈为+
读入* 数值堆栈为20 3 操作符堆栈为+ *
读入5 数值堆栈为20 3 5 操作符堆栈为 + *
读入- 由于+ *的优先级高于或者等于-,所以将3*5计算出15放入堆栈中.然后计算20+15得出35放回堆栈中,数值堆栈为35 操作符堆栈为空.
这种方式要加入括号也很简单.还有更好的方式就是下一个类似于yacc的东东.很容易实现这个功能的.
将表达式改写成后缀式表达式:
(2+3)*2 --> 23+2*