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
4Filename : eval.cpp
5Compiler : Visual C++ 8.0 / ISO C++
6Description : Demo how to implement eval() by C++
7Release : 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
25public:
26 Expression();
27 Expression(const char*);
28
29// public member function
30public:
31 double eval(); // get eval result
32
33// private data member
34private:
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
41private:
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(C) OOMusou 2007 http://oomusou.cnblogs.com
3
4Filename : eval.cpp
5Compiler : Visual C++ 8.0 / ISO C++
6Description : Demo how to implement eval() by C++
7Release : 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
25public:
26 Expression();
27 Expression(const char*);
28
29// public member function
30public:
31 double eval(); // get eval result
32
33// private data member
34private:
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
41private:
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}
執行結果
x1
=
519.75
x2 = 19.6667
請按任意鍵繼續 . . .
x2 = 19.6667
請按任意鍵繼續 . . .
Reference
看程式實例學資料結構 使用Turbo C P.5-25 ~ P.5-54, 洪錦魁, 文魁出版社