表达式求值
[参考文献:严蔚敏.数据结构(C语言版)]
表达式求值是程序设计语言编译中的一个最基本问题,它的实现是栈应用的一个典型例子.
搞了一天,有相关的好的算法请大家传上来,一起分享.
表3.1: 定义了算符之间的优先关系:
代码
1 using System;
2 using System.Collections;
3 using System.Collections.Generic;
4 using System.Linq;
5 using System.Text;
6 using System.Text.RegularExpressions;
7 namespace EvaluateExpression
8 {
9 class EvaluateExpression
10 {
11 private static string Precede(string t1, string t2) //根据表3.1,判断两符号的优先关系
12 {
13 string f = string.Empty;
14 switch (t2)
15 {
16 case "+":
17 case "-":
18 if (t1 == "(" || t1 == "#")
19 f = "<";
20 else
21 f = ">";
22 break;
23 case "*":
24 case "/":
25 if (t1 == "*" || t1 == "/" || t1 == ")")
26 f = ">";
27 else
28 f = "<";
29 break;
30 case "(":
31 if (t1 == ")")
32 throw new ArgumentOutOfRangeException("表达式错误");
33 else
34 f = "<";
35 break;
36 case ")":
37 switch (t1)
38 {
39 case "(": f = "="; break;
40 case "#": throw new ArgumentOutOfRangeException("表达式错误");
41 default: f = ">"; break;
42 }
43 break;
44 case "#":
45 switch (t1)
46 {
47 case "#": f = "="; break;
48 case "(": throw new ArgumentOutOfRangeException("表达式错误");
49 default: f = ">"; break;
50 }
51 break;
52 }
53 return f;
54 }
55 private static bool In(string c) //判断c是否为运算符
56 {
57 switch(c)
58 {
59 case"+":
60 case"-":
61 case"*":
62 case"/":
63 case"(":
64 case")":
65 case"#": return true ;
66 default: return false ;
67 }
68 }
69 private static int Operate(int a, string oper, int b)
70 {
71 int c=0;
72 switch (oper)
73 {
74 case "+": c = a + b; break;
75 case "-": c = a - b; break;
76 case "*": c = a * b; break;
77 case "/": c = a / b; break;
78 }
79 return c;
80
81 }
82 public static int Calculate(string exp) //算术表达式求值的算符优先算法。设OPTR和OPND分别为运算符栈和运算数栈
83 {
84
85 expr S = new expr(exp); //将传过来的表达式打包成一个类对象,便于计算
86 string C =string.Empty ;
87 int oper1, oper2;
88 string theta = string.Empty;
89 Stack OPTR = new Stack();
90 OPTR.Push("#");
91 Stack OPND = new Stack();
92 C = S.GetS (); //取表达式里的分量
93 while (C != "#" || OPTR.Peek().ToString() != "#")
94 {
95 if (!In(C)) //不是运算符则进栈
96 {
97 OPND.Push(C);
98 C = S.GetS();
99 }
100 else
101 switch (Precede(OPTR.Peek().ToString(), C))
102 {
103 case "<": //栈顶元素优先权低
104 OPTR.Push(C);
105 C = S.GetS();
106 break;
107 case "=": //脱括号并接收下一个字符
108 OPTR.Pop();
109 C = S.GetS();
110 break;
111 case ">": //退栈并将运算结果入栈
112 theta = OPTR.Pop().ToString();
113 oper2 = Convert.ToInt32(OPND.Pop());
114 oper1 = Convert.ToInt32(OPND.Pop());
115 OPND.Push(Operate(oper1, theta, oper2).ToString());
116 break;
117 }//switch
118 }//while
119 return Convert.ToInt32(OPND.Peek());
120 }
121 private class expr //表达式类, 用于取表达式里的各个分量
122 {
123 //成员
124 private string exp;
125 private int length; //为GetS()方法服务
126 //构造器
127 public expr(string exp)
128 {
129 this.exp = exp;
130 length = exp.Length;
131 if (!IsRight()) { Console.WriteLine("表达式有错"); return; }
132 }
133 //方法
134 public string GetS() //取表达式里的字符串
135 {
136 string ch, token, f;
137 ch = token = f = string.Empty;
138 if (length == 0)
139 throw new ArgumentOutOfRangeException("表达式取完");
140 while (length != 0)
141 {
142 ch = exp.Substring(exp.Length - length, 1);
143
144 if (IsNumeric(ch)) //是数字 : 说明第一次取的就是数字
145 {
146 token += ch;
147 length--;
148 }
149 else //不是数字
150 {
151 if (IsNumeric(token))
152 {
153 f = token;
154 break;
155 }
156 else //说明第一次取的就不是数字
157 {
158 if (ch == " ")
159 {
160 length--;
161 continue;
162 }
163 length--; //如取的是非数字
164 f = ch;
165 break;
166 }
167 }
168 }
169 return f;
170 }//GetS
171 private bool IsRight() //判断表达式是否合法: (1)两数字中间是否有空格
172 {
173 bool f = true;
174 string ch = string.Empty;
175 int i = 0;
176 int j = 0;
177 for (int p = 0; p < exp.Length; p++)
178 {
179 ch = exp.Substring(p, 1);
180 if (IsNumeric(ch))
181 {
182 if (j == 1) return false;
183 i = 1;
184 continue;
185 }
186 if (ch == " ")
187 {
188 if (i == 1) j = 1; continue;
189 }
190 i = j = 0;
191
192 }
193 return f;
194
195 }
196 private bool IsNumeric(string input) //判断字符串是否为数
197 {
198 bool flag = true;
199 string pattern = (@"^\d+$");
200 Regex validate = new Regex(pattern);
201 if (!validate.IsMatch(input))
202 {
203 flag = false;
204 }
205 return flag;
206 }
207 }//class:expr
208 }
209 }
210 附一个测试代码:
211 using System;
212 using System.Collections.Generic;
213 using System.Linq;
214 using System.Text;
215 namespace EvaluateExpression
216 {
217 class Program
218 {
219 static void Main(string[] args)
220 {
221 Console.WriteLine ("算术表达式, 以#结束!");
222 string expression = " 3022 * ( 17 - 12) /2 #";
223 Console .WriteLine ( Convert .ToString ( EvaluateExpression.Calculate(expression)));
224 Console.ReadLine();
225 }
226 }
227 }
2 using System.Collections;
3 using System.Collections.Generic;
4 using System.Linq;
5 using System.Text;
6 using System.Text.RegularExpressions;
7 namespace EvaluateExpression
8 {
9 class EvaluateExpression
10 {
11 private static string Precede(string t1, string t2) //根据表3.1,判断两符号的优先关系
12 {
13 string f = string.Empty;
14 switch (t2)
15 {
16 case "+":
17 case "-":
18 if (t1 == "(" || t1 == "#")
19 f = "<";
20 else
21 f = ">";
22 break;
23 case "*":
24 case "/":
25 if (t1 == "*" || t1 == "/" || t1 == ")")
26 f = ">";
27 else
28 f = "<";
29 break;
30 case "(":
31 if (t1 == ")")
32 throw new ArgumentOutOfRangeException("表达式错误");
33 else
34 f = "<";
35 break;
36 case ")":
37 switch (t1)
38 {
39 case "(": f = "="; break;
40 case "#": throw new ArgumentOutOfRangeException("表达式错误");
41 default: f = ">"; break;
42 }
43 break;
44 case "#":
45 switch (t1)
46 {
47 case "#": f = "="; break;
48 case "(": throw new ArgumentOutOfRangeException("表达式错误");
49 default: f = ">"; break;
50 }
51 break;
52 }
53 return f;
54 }
55 private static bool In(string c) //判断c是否为运算符
56 {
57 switch(c)
58 {
59 case"+":
60 case"-":
61 case"*":
62 case"/":
63 case"(":
64 case")":
65 case"#": return true ;
66 default: return false ;
67 }
68 }
69 private static int Operate(int a, string oper, int b)
70 {
71 int c=0;
72 switch (oper)
73 {
74 case "+": c = a + b; break;
75 case "-": c = a - b; break;
76 case "*": c = a * b; break;
77 case "/": c = a / b; break;
78 }
79 return c;
80
81 }
82 public static int Calculate(string exp) //算术表达式求值的算符优先算法。设OPTR和OPND分别为运算符栈和运算数栈
83 {
84
85 expr S = new expr(exp); //将传过来的表达式打包成一个类对象,便于计算
86 string C =string.Empty ;
87 int oper1, oper2;
88 string theta = string.Empty;
89 Stack OPTR = new Stack();
90 OPTR.Push("#");
91 Stack OPND = new Stack();
92 C = S.GetS (); //取表达式里的分量
93 while (C != "#" || OPTR.Peek().ToString() != "#")
94 {
95 if (!In(C)) //不是运算符则进栈
96 {
97 OPND.Push(C);
98 C = S.GetS();
99 }
100 else
101 switch (Precede(OPTR.Peek().ToString(), C))
102 {
103 case "<": //栈顶元素优先权低
104 OPTR.Push(C);
105 C = S.GetS();
106 break;
107 case "=": //脱括号并接收下一个字符
108 OPTR.Pop();
109 C = S.GetS();
110 break;
111 case ">": //退栈并将运算结果入栈
112 theta = OPTR.Pop().ToString();
113 oper2 = Convert.ToInt32(OPND.Pop());
114 oper1 = Convert.ToInt32(OPND.Pop());
115 OPND.Push(Operate(oper1, theta, oper2).ToString());
116 break;
117 }//switch
118 }//while
119 return Convert.ToInt32(OPND.Peek());
120 }
121 private class expr //表达式类, 用于取表达式里的各个分量
122 {
123 //成员
124 private string exp;
125 private int length; //为GetS()方法服务
126 //构造器
127 public expr(string exp)
128 {
129 this.exp = exp;
130 length = exp.Length;
131 if (!IsRight()) { Console.WriteLine("表达式有错"); return; }
132 }
133 //方法
134 public string GetS() //取表达式里的字符串
135 {
136 string ch, token, f;
137 ch = token = f = string.Empty;
138 if (length == 0)
139 throw new ArgumentOutOfRangeException("表达式取完");
140 while (length != 0)
141 {
142 ch = exp.Substring(exp.Length - length, 1);
143
144 if (IsNumeric(ch)) //是数字 : 说明第一次取的就是数字
145 {
146 token += ch;
147 length--;
148 }
149 else //不是数字
150 {
151 if (IsNumeric(token))
152 {
153 f = token;
154 break;
155 }
156 else //说明第一次取的就不是数字
157 {
158 if (ch == " ")
159 {
160 length--;
161 continue;
162 }
163 length--; //如取的是非数字
164 f = ch;
165 break;
166 }
167 }
168 }
169 return f;
170 }//GetS
171 private bool IsRight() //判断表达式是否合法: (1)两数字中间是否有空格
172 {
173 bool f = true;
174 string ch = string.Empty;
175 int i = 0;
176 int j = 0;
177 for (int p = 0; p < exp.Length; p++)
178 {
179 ch = exp.Substring(p, 1);
180 if (IsNumeric(ch))
181 {
182 if (j == 1) return false;
183 i = 1;
184 continue;
185 }
186 if (ch == " ")
187 {
188 if (i == 1) j = 1; continue;
189 }
190 i = j = 0;
191
192 }
193 return f;
194
195 }
196 private bool IsNumeric(string input) //判断字符串是否为数
197 {
198 bool flag = true;
199 string pattern = (@"^\d+$");
200 Regex validate = new Regex(pattern);
201 if (!validate.IsMatch(input))
202 {
203 flag = false;
204 }
205 return flag;
206 }
207 }//class:expr
208 }
209 }
210 附一个测试代码:
211 using System;
212 using System.Collections.Generic;
213 using System.Linq;
214 using System.Text;
215 namespace EvaluateExpression
216 {
217 class Program
218 {
219 static void Main(string[] args)
220 {
221 Console.WriteLine ("算术表达式, 以#结束!");
222 string expression = " 3022 * ( 17 - 12) /2 #";
223 Console .WriteLine ( Convert .ToString ( EvaluateExpression.Calculate(expression)));
224 Console.ReadLine();
225 }
226 }
227 }
本文转自:http://www.cnblogs.com/wwewbw/archive/2010/02/11/1667538.html