C/C++都是靜態語言,所以都沒有eval()這個函數,C#也沒有,在.NET語言中,只有JScript.NET有eval(),連VB也沒有,事實上,eval()是很好用的,以前在寫VFP時,常常利用字串湊程式,然後用eval()去執行,來到C#,一直想用eval(),若真的想在C#用,可以偷用JScript.NET的,有時間會另外討論這個主題。
在此程式我們試著用C++寫一個eval(),不過這個eval()功能有限,只能處理四則運算加上括號而已,在很多資料結構講stack的地方,會用C語言利用stack來寫,事實上,本程式也是參考『看程式實例學資料結構 使用Turbo C』的範例加以修改成C++和STL,以及OOP方式。
本程式的演算法是,先將人類習慣的『中序運算式』表示法先改成『後序運算式』表示法,因為後序式不需考慮括號的處理,比較簡單,然後再加以運算。
1
/**/
/*
2
(C) OOMusou 2007 http://oomusou.cnblogs.com
3
4
Filename : eval.cpp
5
Compiler : Visual C++ 8.0 / ISO C++
6
Description : Demo how to implement eval() by C++
7
Release : 01/06/2007 1.0
8
*/
9
10
#include
<
iostream
>
//
cout
11
#include
<
string
>
//
string
12
#include
<
sstream
>
//
stringstream
13
#include
<
stack
>
//
stack
14
#include
<
vector
>
//
vector
15
#include
<
cctype
>
//
isdigit()
16
17
using
namespace
std;
18
19
//
define const variable for readability
20
const
int
OPERATOR
=
0
;
21
const
int
OPERAND
=
1
;
22
23
class
Expression
{
24
// constructor
25
public:
26
Expression();
27
Expression(const char*);
28
29
// public member function
30
public:
31
double eval(); // get eval result
32
33
// private data member
34
private:
35
stack<double> operandStack; // stack to store operand
36
stack<char> operatorStack; // stack to store operator
37
string infix; // string to hold infix expression
38
vector<pair<int, string> > suffix; // vector to hold suffix expression
39
40
// private member function
41
private:
42
string char2str(const char &); // convert char to string
43
string dbl2str(const double &); // convert double to string
44
double str2dbl(const string &); // convert string to double
45
bool isoperator(const char &); // identify whether it is an operator
46
void parseOperand(const double &); // parse operand to operandStack
47
void parseOperator(const char &); // parse operator to operatorStack
48
int operatorPriority(const char&); // define operator priority
49
void toSuffix(void); // convert infix to suffix
50
double calculate(const string &, const double &, const double &); // calculate result by operator and operand
51
}
;
52
53
int
main(
void
)
{
54
Expression x1("123/4+123*4-3");
55
cout << "x1=" << x1.eval() << endl;
56
57
Expression x2("1+(6+8)*4/3");
58
cout << "x2=" << x2.eval() << endl;
59
}
60
61
//
constructor
62
Expression::Expression()
{
63
64
}
65
66
//
constructor
67
Expression::Expression(
const
char
*
val)
{
68
this->infix = string(val); // fill infix by constructor
69
this->toSuffix(); // convert infix to suffix
70
}
71
72
//
convert char to string
73
string
Expression::char2str(
const
char
&
c)
{
74
stringstream ss;
75
ss << c;
76
77
return ss.str();
78
}
79
80
//
convert double to string
81
string
Expression::dbl2str(
const
double
&
d)
{
82
stringstream ss;
83
ss << d;
84
85
return ss.str();
86
}
87
88
//
convert string to double
89
double
Expression::str2dbl(
const
string
&
s)
{
90
stringstream ss(s);
91
double d;
92
ss >> d;
93
94
return d;
95
}
96
97
//
identify whether it is an operator
98
bool
Expression::isoperator(
const
char
&
c)
{
99
switch(c)
{
100
case '(' :
101
case ')' :
102
case '+' :
103
case '-' :
104
case '*' :
105
case '/' : return true;
106
default : return false;
107
}
108
}
109
110
//
parse operand to operandStack
111
void
Expression::parseOperand(
const
double
&
dOperand)
{
112
suffix.push_back(make_pair(OPERAND, dbl2str(dOperand)));
113
}
114
115
//
parse operator to operatorStack
116
void
Expression::parseOperator(
const
char
&
cOperator)
{
117
if (operatorStack.empty() || cOperator == '(')
{
118
operatorStack.push(cOperator);
119
}
120
else
{
121
if (cOperator == ')')
{
122
while(operatorStack.top() != '(')
{
123
suffix.push_back(make_pair(OPERATOR, char2str(operatorStack.top())));
124
operatorStack.pop();
125
126
if (operandStack.empty()) break;
127
}
128
// Remove '('
129
operatorStack.pop();
130
}
131
else
{ // not ')'
132
while(operatorPriority(cOperator) <= operatorPriority(operatorStack.top()) && !operatorStack.empty())
{
133
suffix.push_back(make_pair(OPERATOR, char2str(operatorStack.top())));
134
operatorStack.pop();
135
136
if (operatorStack.empty())
137
break;
138
}
139
operatorStack.push(cOperator);
140
}
141
}
142
}
143
144
//
define operator priority
145
int
Expression::operatorPriority(
const
char
&
cOperator)
{
146
switch(cOperator)
{
147
case '*' :
148
case '/' : return 3;
149
case '+' :
150
case '-' : return 2;
151
case '(' : return 1;
152
default : return 0;
153
}
154
}
155
156
//
Convert infix to suffix
157
//
Algorithm : Parse infix string one char by one char. If char
158
//
is operator, check if _operand is "", if not, let
159
//
_operand to operandStack, and make _operand string
160
//
clear, then let operator to operatorStack. If char
161
//
is digit, concatenate to _operand string.
162
void
Expression::toSuffix(
void
)
{
163
string _operand;
164
for(string::iterator p = infix.begin(); p != infix.end(); ++p)
{
165
if (isoperator(*p))
{
166
if (_operand != "")
{
167
parseOperand(str2dbl(_operand));
168
_operand.clear();
169
}
170
parseOperator(*p);
171
} else if (isdigit(*p))
172
_operand.push_back(*p);
173
}
174
175
// If _operand is not "", let _operand to operandStack.
176
if (_operand != "")
177
parseOperand(str2dbl(_operand));
178
179
// If operatorStack is not empty, push it to suffix vector until
180
// operatorStack is empty.
181
while(!operatorStack.empty())
{
182
suffix.push_back(make_pair(OPERATOR,char2str(operatorStack.top())));
183
operatorStack.pop();
184
}
185
}
186
187
//
calculate result by operator and operand
188
double
Expression::calculate(
const
string
&
op,
const
double
&
operand1,
const
double
&
operand2)
{
189
if (op == "+")
190
return operand2 + operand1;
191
else if (op == "-")
192
return operand2 - operand1;
193
else if (op == "*")
194
return operand2 * operand1;
195
else if (op == "/")
196
return operand2 / operand1;
197
else
198
return 0;
199
}
200
201
//
get eval result
202
double
Expression::eval(
void
)
{
203
// Clear OperandStack
204
while(!operandStack.empty())
205
operandStack.pop();
206
207
for(vector<pair<int, string> >::iterator iter = suffix.begin(); iter != suffix.end(); ++iter)
{
208
if (iter->first == OPERATOR)
{
209
double operand1 = operandStack.top();
210
operandStack.pop();
211
double operand2 = operandStack.top();
212
operandStack.pop();
213
operandStack.push(calculate(iter->second, operand1, operand2));
214
}
215
else if (iter->first == OPERAND)
{
216
operandStack.push(str2dbl(iter->second));
217
}
218
}
219
220
return operandStack.top();
221
}


2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23



24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53



54

55

56

57

58

59

60

61

62



63

64

65

66

67



68

69

70

71

72

73



74

75

76

77

78

79

80

81



82

83

84

85

86

87

88

89



90

91

92

93

94

95

96

97

98



99



100

101

102

103

104

105

106

107

108

109

110

111



112

113

114

115

116



117



118

119

120



121



122



123

124

125

126

127

128

129

130

131



132



133

134

135

136

137

138

139

140

141

142

143

144

145



146



147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162



163

164



165



166



167

168

169

170

171

172

173

174

175

176

177

178

179

180

181



182

183

184

185

186

187

188



189

190

191

192

193

194

195

196

197

198

199

200

201

202



203

204

205

206

207



208



209

210

211

212

213

214

215



216

217

218

219

220

221

執行結果



Reference
看程式實例學資料結構 使用Turbo C P.5-25 ~ P.5-54, 洪錦魁, 文魁出版社