C# 中实现表达式计算
2011-10-05 13:25
351 查看
提要:
1.对上一篇文章的改进:增加括号
2.改变了字符串转化成中缀表达式的方法
一、依旧是数据结构的知识:
1.将中缀表达式转换成后缀表达式
设算法的输入为中缀表达式infixExp(字符串),输出结果为postfixExp,是保值的后缀表达式。
举例:23+34*45/(5+6+7) 转后为后缀: 23 34 45 * 5 6 + 7 + / +
2.算法:
自左至右扫描infixExp,读入每项并分析其对应的语法成分:
1)当输入的是操作数,则直接输出到postfixExp中。
2)当输入的是左括号,则把它压栈。
3)当输入的是右括号,先判断栈是否为空,若为空则括号不匹配;若非空,则把栈中的项依次弹出,直到遇到第1个左括号为止,将弹出的项输出到postfixExp中(弹出的左括号不输出到postfixExp中),若没有遇到左括号,则括号也不匹配。
4)当输入的是运算符op(四则运算+-*/之一)时:
a)循环,当(栈非空and栈顶不是左括号and栈顶运算符的优先级不低于输入运算符的优先级时),反复操作:将栈顶元素弹出,输出到postfixExp中。
b)把输入的运算符op压栈。
5)最后,当中缀表达式infixExp的符号序列全部读入后,在栈中可能还会一些项,它们是原来压入还没有处理的语法成分。对待它们的方法是:把它们依次从栈中弹出,并输出到后缀表达式postfixExp的尾部。
2.后缀的求值见上一篇文章
二、将字符串变成中缀表达式,保存到Q1中
在没有想到很好的算法。就是将字符串进行分割,把数值保存到分割后的数组resSplit中,然后对原来的字符串res遍历,寻找运算符。
期待找到更好的算法。
//按钮"="的响应代码
protectedvoidButtonEqual_Click(objectsender,EventArgse)
{
intsi=0;
ints=1;//s=0时:上一个元素是数字。s=1时,上一个是符号
Stringres=TextBoxResult.Text;
char[]str=TextBoxResult.Text.ToCharArray();
string[]resSplit=res.Split(newchar[]{'+','-','*','/','(',')'});
try
{
for(inti=0;i<str.Length;i++)
{
nodetmp=newnode();//临时节点
if((str[i]==46||(str[i]-48<=9&&0<=str[i]-48))&&s==1)//新加入的元素是数值
{
tmp.sign=false;
while(true)
{
if(resSplit[si]!="")
{
tmp.num=Convert.ToDouble(resSplit[si]);
break;
}
elsesi++;
}
Q1.Enqueue(tmp);
Label1.Text=Label1.Text+tmp.num;//测试
s=0;
si++;
}
elseif((str[i]==46||(str[i]-48<=9&&0<=str[i]-48))&&s==0)//新加入的元素是数字,但前面元素也是
{
continue;
}
else
{
tmp.sign=true;
tmp.symbol=str[i];
if(tmp.symbol=='*'||tmp.symbol=='/')tmp.priority=2;
elseif(tmp.symbol=='+'||tmp.symbol=='-')tmp.priority=1;
s=1;
Q1.Enqueue(tmp);
Label1.Text=Label1.Text+tmp.symbol;//测试
}
}
change();
doubler=calculate();
if(err==false)Label1.Text=Label1.Text+"="+r+"<br/>";
else Label1.Text=Label1.Text+"error!<br/>";//测试
}
catch(Exceptionew)
{
Label1.Text=Label1.Text+"error!<br/>";//测试
}
}
三中缀-后缀
publicvoidchange()//2)将中缀表达式转换成后缀表达式;
{
while(Q1.Count!=0)
{
if(Q1.Peek().sign==false)//是数字,放入队列
{
Q2.Enqueue(Q1.Peek());
}
else
{
if(Q1.Peek().symbol=='(')//当输入的是左括号,则把它压栈。
Sc.Push(Q1.Peek());
elseif(Q1.Peek().symbol==')')//当输入的是右括号,
{
if(Sc.Count()==0)
{
err=true;
break;
}
else
{
while(Sc.Peek().symbol!='(')
{
Q2.Enqueue(Sc.Peek());
Sc.Pop();
if(Sc.Count()==0)
{
err=true;
break;
}
}
if(Sc.Count()!=0) Sc.Pop();
}
}
else
{
while(Sc.Count()!=0&&Q1.Peek().symbol!='('&&Q1.Peek().priority<=Sc.Peek().priority)
{
Q2.Enqueue(Sc.Peek());
Sc.Pop();
}
Sc.Push(Q1.Peek());
}
}
Q1.Dequeue();
}
while(Sc.Count()!=0)
{
if(Sc.Peek().symbol=='(')
{
err=true;
break;
}
Q2.Enqueue(Sc.Peek());
Sc.Pop();
}
}
四后缀求解
五、不足:
1随便写了点,代码还很不规范
2出现错误时全部报错error!,未进行细分
3限制为double型,无法达到高精度
4不支持负数,如-6计算时会出错,需写成:(0-6)
1.对上一篇文章的改进:增加括号
2.改变了字符串转化成中缀表达式的方法
一、依旧是数据结构的知识:
1.将中缀表达式转换成后缀表达式
设算法的输入为中缀表达式infixExp(字符串),输出结果为postfixExp,是保值的后缀表达式。
举例:23+34*45/(5+6+7) 转后为后缀: 23 34 45 * 5 6 + 7 + / +
2.算法:
自左至右扫描infixExp,读入每项并分析其对应的语法成分:
1)当输入的是操作数,则直接输出到postfixExp中。
2)当输入的是左括号,则把它压栈。
3)当输入的是右括号,先判断栈是否为空,若为空则括号不匹配;若非空,则把栈中的项依次弹出,直到遇到第1个左括号为止,将弹出的项输出到postfixExp中(弹出的左括号不输出到postfixExp中),若没有遇到左括号,则括号也不匹配。
4)当输入的是运算符op(四则运算+-*/之一)时:
a)循环,当(栈非空and栈顶不是左括号and栈顶运算符的优先级不低于输入运算符的优先级时),反复操作:将栈顶元素弹出,输出到postfixExp中。
b)把输入的运算符op压栈。
5)最后,当中缀表达式infixExp的符号序列全部读入后,在栈中可能还会一些项,它们是原来压入还没有处理的语法成分。对待它们的方法是:把它们依次从栈中弹出,并输出到后缀表达式postfixExp的尾部。
2.后缀的求值见上一篇文章
二、将字符串变成中缀表达式,保存到Q1中
在没有想到很好的算法。就是将字符串进行分割,把数值保存到分割后的数组resSplit中,然后对原来的字符串res遍历,寻找运算符。
期待找到更好的算法。
//按钮"="的响应代码
protectedvoidButtonEqual_Click(objectsender,EventArgse)
{
intsi=0;
ints=1;//s=0时:上一个元素是数字。s=1时,上一个是符号
Stringres=TextBoxResult.Text;
char[]str=TextBoxResult.Text.ToCharArray();
string[]resSplit=res.Split(newchar[]{'+','-','*','/','(',')'});
try
{
for(inti=0;i<str.Length;i++)
{
nodetmp=newnode();//临时节点
if((str[i]==46||(str[i]-48<=9&&0<=str[i]-48))&&s==1)//新加入的元素是数值
{
tmp.sign=false;
while(true)
{
if(resSplit[si]!="")
{
tmp.num=Convert.ToDouble(resSplit[si]);
break;
}
elsesi++;
}
Q1.Enqueue(tmp);
Label1.Text=Label1.Text+tmp.num;//测试
s=0;
si++;
}
elseif((str[i]==46||(str[i]-48<=9&&0<=str[i]-48))&&s==0)//新加入的元素是数字,但前面元素也是
{
continue;
}
else
{
tmp.sign=true;
tmp.symbol=str[i];
if(tmp.symbol=='*'||tmp.symbol=='/')tmp.priority=2;
elseif(tmp.symbol=='+'||tmp.symbol=='-')tmp.priority=1;
s=1;
Q1.Enqueue(tmp);
Label1.Text=Label1.Text+tmp.symbol;//测试
}
}
change();
doubler=calculate();
if(err==false)Label1.Text=Label1.Text+"="+r+"<br/>";
else Label1.Text=Label1.Text+"error!<br/>";//测试
}
catch(Exceptionew)
{
Label1.Text=Label1.Text+"error!<br/>";//测试
}
}
三中缀-后缀
publicvoidchange()//2)将中缀表达式转换成后缀表达式;
{
while(Q1.Count!=0)
{
if(Q1.Peek().sign==false)//是数字,放入队列
{
Q2.Enqueue(Q1.Peek());
}
else
{
if(Q1.Peek().symbol=='(')//当输入的是左括号,则把它压栈。
Sc.Push(Q1.Peek());
elseif(Q1.Peek().symbol==')')//当输入的是右括号,
{
if(Sc.Count()==0)
{
err=true;
break;
}
else
{
while(Sc.Peek().symbol!='(')
{
Q2.Enqueue(Sc.Peek());
Sc.Pop();
if(Sc.Count()==0)
{
err=true;
break;
}
}
if(Sc.Count()!=0) Sc.Pop();
}
}
else
{
while(Sc.Count()!=0&&Q1.Peek().symbol!='('&&Q1.Peek().priority<=Sc.Peek().priority)
{
Q2.Enqueue(Sc.Peek());
Sc.Pop();
}
Sc.Push(Q1.Peek());
}
}
Q1.Dequeue();
}
while(Sc.Count()!=0)
{
if(Sc.Peek().symbol=='(')
{
err=true;
break;
}
Q2.Enqueue(Sc.Peek());
Sc.Pop();
}
}
四后缀求解
publicdoublecalculate()
{
Stack<node>stmp=newStack<node>();
doublenum1=0;
doublenum2=0;
nodetmp=newnode();
while(Q2.Count!=0)
{
if(Q2.Peek().sign==false)
{
stmp.Push(Q2.Peek());
}
elseif(Q2.Peek().sign==true)
{
num2=stmp.Peek().num;
stmp.Pop();
num1=stmp.Peek().num;
stmp.Pop();
if(Q2.Peek().symbol=='+')
{
tmp.num=num1+num2;
tmp.priority=1;
tmp.sign=false;
}
elseif(Q2.Peek().symbol=='-')
{
tmp.num=num1-num2;
tmp.priority=1;
tmp.sign=false;
}
elseif(Q2.Peek().symbol=='*')
{
tmp.num=num1*num2;
tmp.priority=2;
tmp.sign=false;
}
elseif(Q2.Peek().symbol=='/')
{
tmp.num=num1/num2;
tmp.priority=2;
tmp.sign=false;
}
stmp.Push(tmp);
}
Q2.Dequeue();
}
if(stmp.Count()!=1)err=true;
returnstmp.Peek().num;
}
五、不足:
1随便写了点,代码还很不规范
2出现错误时全部报错error!,未进行细分
3限制为double型,无法达到高精度
4不支持负数,如-6计算时会出错,需写成:(0-6)
相关文章推荐
- C#中实现字符串表达式计算
- C#实现的表达式解析与计算类TExprParser介绍
- 数据结构之应用 "栈(Stack)" 实现: 解析算术表达式及计算求值 (C#/Java)
- 数据结构习作之应用 "栈(Stack)" 实现: 解析算术表达式及计算求值 (C#/Java) (技术含量少许)
- C#利用js脚本实现配置的文本表达式计算
- c#中实现类似js的Eval|.NET中执行Javascript(表达式是字符串的计算)
- 数据结构之应用 "栈(Stack)" 实现: 解析算术表达式及计算求值 (C#/Java) (转载)
- 数据结构之应用 "栈(Stack)" 实现: 解析算术表达式及计算求值 (C#/Java)
- 数据结构中用C#实现“表达式计算”
- C# 中实现表达式计算
- 数据结构之应用 "栈(Stack)" 实现: 解析算术表达式及计算求值 (C#/Java)
- 数据结构之应用 "栈(Stack)" 实现: 解析算术表达式及计算求值 (C#/Java)
- 数据结构中用C#实现"表达式计算"
- [转载]数据结构中用C#实现"表达式计算"
- 计算计算机网络的可靠度---因子定理计算网络可靠度的算法C#代码实现
- java实现中缀表达式转后缀表达式并且计算
- C++实现 逆波兰表达式计算问题
- 完全利用栈实现表达式的计算问题
- Java实现表达式计算(中缀表达式转化为后缀表达式/逆波兰式)
- C#中利用正则表达式实现字符串搜索