C/C++都是靜態語言,所以都沒有eval_r()這個函數,C#也沒有,在.NET語言中,只有JScript.NET有eval_r(),連VB也沒有,事實上,eval_r()是很好用的,以前在寫VFP時,常常利用字串湊程式,然後用eval_r()去執行,來到C#,一直想用eval_r(),若真的想在C#用,可以偷用JScript.NET的,有時間會另外討論這個主題。
在此程式我們試著用C++寫一個eval_r(),不過這個eval_r()功能有限,只能處理四則運算加上括號而已,在很多資料結構講stack的地方,會用C語言利用stack來寫,事實上,本程式也是參考『看程式實例學資料結構
使用Turbo C』的範例加以修改成C++和STL,以及OOP方式。
本程式的演算法是,先將人類習慣的『中序運算式』表示法先改成『後序運算式』表示法,因為後序式不需考慮括號的處理,比較簡單,然後再加以運算。
1
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
17using namespace std;
18
19// define const variable for readability
20const int OPERATOR = 0;
21const int OPERAND = 1;
22
23class Expression {
24// constructor
25public:
26 expression_r();
27 expression_r(const
char*);
28
29// public member function
30public:
31 double eval_r(); // 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
53int main(void) {
54 Expression
x1("123/4+123*4-3");
55 cout
<< "x1="
<< x1.eval_r()
<< endl;
56
57 Expression
x2("1+(6+8)*4/3");
58 cout
<< "x2="
<< x2.eval_r()
<< endl;
59}
60
61// constructor
62Expression::expression_r() {
63
64}
65
66// constructor
67Expression::expression_r(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
73string Expression::char2str(const char
&c) {
74 stringstream ss;
75 ss
<< c;
76
77 return ss.str();
78}
79
80// convert double to string
81string Expression::dbl2str(const double
&d) {
82 stringstream ss;
83 ss
<< d;
84
85 return ss.str();
86}
87
88// convert string to double
89double 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
98bool 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
111void Expression::parseOperand(const double
&dOperand) {
112 suffix.push_back(make_pair(OPERAND,
dbl2str(dOperand)));
113}
114
115// parse operator to operatorStack
116void 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