九天雁翎的博客
如果你想在软件业获得成功,就使用你知道的最强大的语言,用它解决你知道的最难的问题,并且等待竞争对手的经理做出自甘平庸的选择。 -- Paul Graham

堆栈的应用(2) 中缀算术表达式到后缀(逆波兰记法reverse polish notation)的转换及其计算 C++实现


 堆栈的应用(2
中缀算术表达式到后缀(逆波兰记法reverse polish notation)的转换及其计算 C++实现

write by 九天雁翎(JTianLing) --
blog.csdn.net/vagrxie

 

<<Data Structures and Algorithm Analysis in C++>>

--《数据结构与算法分析c++描述》 Mark Allen Weiss 人民邮电大学出版 中文版第73-77面,中缀算术表达式到后缀(逆波兰记法reverse polish notation)的转换及其计算

       目前仅仅实现文中说明的功能,目标并不是一个完整的四则运算程序,所以只支持加法,乘法和()。另外,因为对于C++流的控制能力比较弱(我下一步就决定好好研究研究),所以对输入的格式要求非常严格。

必须是1 + 2 * 3 =

的格式,每个数字和符号之间都需要空格,一个比较复杂的例子是:

1 + 2 *
3 + ( 1 + 2 * 3 ) =

转换后:

1 2 3 *
+ 1 2 3 * + + =

先看测试程序,就应该能知道,大概实现了什么效果了,这里唯一的便利在于,用了C++的输入输出流后,对于iostream,stringstream都比较一致了,但是还是感觉自己对流的控制能力太弱了。

test.cpp:

 1 #include <stdio.h>
 2 #include
<stdlib.h>
 3 #include
<stack>
 4 #include
<string> 
 5 #include
<iostream> 
 6 #include
<sstream>
 7 #include
"ExprComputer.h"
 8 using namespace std;
 9
10 int main(int argc, char*
argv[])
11 {
12     CExprComputer
loExprComputer;
13     // all these below can work right,comment is same as the
content 'couted'.

14     stringstream lss;
15     lss << "1 + 2 * 3 =";
16
17     cout <<"test trans stringstream in and cout." <<endl;
18     loExprComputer.TransInfix2Postfix(lss,
cout);
19
20     cout <<"test trans cin and cout." <<endl;
21     loExprComputer.TransInfix2Postfix(cin,
cout);
22
23     stringstream
lss2;
24     cout <<"test trans cin and stringstream out." <<endl;
25     loExprComputer.TransInfix2Postfix(cin,
lss2);
26     cout
<<lss2.str() <<endl;
27
28     lss.seekg(0);
29     cout <<"test stringstream in computeInfix." <<endl;
30     cout
<<lss.str();
31     cout
<<loExprComputer.ComputeInfix(lss) <<endl;
32
33     cout <<"test cin in computeInfix." <<endl;
34     cout
<<loExprComputer.ComputeInfix(cin) <<endl;
35
36     stringstream
lssPostfix;
37     lssPostfix
<< "1 2 3 * + =";
38     cout <<"test stringstream in ComputePostfix." <<endl;
39     cout
<<lssPostfix.str();
40     cout
<<loExprComputer.ComputePostfix(lssPostfix) <<endl;
41
42     cout <<"test cin in ComputePostfix." <<endl;
43     cout
<<loExprComputer.ComputePostfix(cin) <<endl;
44  
45     cout <<"Test completed." <<endl;
46     exit(0);
47 }
48

 

 

ExprComputer头文件:

1 #ifndef __EXPR_COMPUTE_H__
 2 #define
__EXPR_COMPUTE_H__

 3 #include
<iostream> 
 4 #include
<sstream>
 5 #include
<stack> 
 6 using namespace std;
 7
 8 // argument
to input

 9 #define
_IN_

10
11 // argument to
output

12 #define _OUT_
13
14 class CExprComputer
15 {
16 public:
17     int ComputeInfix(_IN_ istream&
aisExpr);
18     int ComputePostfix(_IN_ istream&
aisExpr);
19
20     // Transform a infix expression to Postfix expression
21     int TransInfix2Postfix(_IN_ istream&
aisInfix,
22             _OUT_
ostream& aosPostfix);
23
24 private:
25     // Stack should be empty,Dump the information still in Stack
and exit

26     void DumpStack();
27
28     // Output all information still in Stack
29     void OutputStack();
30
31     // Make sure Stack is not empty when it should not.
32     void CheckStack();
33
34     // I don't know why Stack operator is so few.And why I need
to

35     // clear the Stack in this example? GOD knows.
36     void ClearStack();
37
38     // Read a int or a operator from a stream
39     bool ReadStream(_IN_ istream&
aisExpr, _OUT_ int&
aiReaded,  _OUT_ bool&
abIsChar);
40
41     // Process a Operator
42     void ProcessOperator(char ac, _OUT_ ostream& aosPostfix);
43
44     void ComputeOperator(char ac);
45
46     stack<int> miSta;
47 };
48
49
50
51
52
53 #endif
54

 

cpp 文件:

  1 #include "ExprComputer.h"
  2
  3 void CExprComputer::DumpStack()
  4 {
  5     if(!miSta.empty())
  6     {
  7         cout
<<"stack: ";
  8         OutputStack();
  9         cout
<<endl;
 10         exit(1);
 11     }
 12
 13 }
 14
 15 void CExprComputer::OutputStack()
 16 {
 17     while(!miSta.empty())
 18     {
 19         cout
<<miSta.top() <<" ";
 20         miSta.pop();
 21     }
 22 }
 23
 24 void CExprComputer::ClearStack()
 25 {
 26     while(!miSta.empty())
 27     {
 28         miSta.pop();
 29     }
 30 }
 31
 32 void CExprComputer::CheckStack()
 33 {
 34     if(    miSta.empty() )
 35     {
 36         cout
<<"Invalid expression input." <<endl;
 37         exit(1);
 38     }
 39 }
 40
 41 bool CExprComputer::ReadStream(_IN_
istream& aisExpr, _OUT_ int&
aiReaded,  _OUT_ bool&
abIsChar)
 42 {
 43     if(aisExpr.eof())
 44     {
 45         return false;
 46     }
 47
 48     // try to read stream as a int
 49     abIsChar = false;
 50     int li;
 51     aisExpr
>> li;
 52
 53     // if next thing in stream is not a int, back a char and
read it

 54     if(aisExpr.fail())
 55     {
 56         aisExpr.clear();
 57         aisExpr.unget();
 58         char c;
 59         aisExpr
>> c;
 60         if(c != '=')
 61         {
 62             aiReaded
= c;
 63             abIsChar
= true;
 64             return true;
 65         }
 66         else
 67         {
 68             return false;
 69         }
 70     }
 71
 72     aiReaded =
li;
 73     return true;
 74 }
 75
 76
 77 void CExprComputer::ProcessOperator(char ac, _OUT_ ostream& aosPostfix)
 78 {
 79     switch(ac)
 80     {
 81         case '(':
 82         {
 83             // save the '('
 84             miSta.push(ac);
 85             break;
 86         }
 87         case ')':
 88         {
 89             char lc;
 90             CheckStack();
 91
 92             // output all operator until find a '('
 93             while( (lc = miSta.top()) != '(' )
 94             {
 95                 aosPostfix
<< lc <<" ";
 96                 miSta.pop();
 97                 CheckStack();
 98             }
 99
100             // the first '(' in stack,We just need pop it
101             miSta.pop();
102             break;
103         }
104         case '*':
105         {
106             char lc;
107
108             // output all operator until find a lower level operator
109             while( !miSta.empty() &&
110                     ((lc
= miSta.top()) != '(') &&
111                     (
lc != '+') )
112             {
113                 aosPostfix
<<lc <<" ";
114                 miSta.pop();
115             }
116
117             miSta.push(ac);
118             break;
119         }
120         case '+':
121         {
122
123             char lc;
124
125             // output all operator until find a lower level operator
126             while( !miSta.empty() &&
127                     ((lc
= miSta.top()) != '(') )
128             {
129                 aosPostfix
<<lc <<" ";
130                 miSta.pop();
131             }
132
133             miSta.push(ac);
134             break;
135         }
136         default:
137         {
138             cout
<<"Don't support this operator." <<endl;
139             exit(1);
140         }
141     }
142
143 }
144
145 int CExprComputer::TransInfix2Postfix(_IN_
istream& aisInfix,
146         _OUT_
ostream& aosPostfix)
147 {
148     int li = 0;
149     bool lbIsChar = false;
150     while( ReadStream(aisInfix, li, lbIsChar) )
151     {
152         // number need immediately output
153         if(!lbIsChar)
154         {
155             aosPostfix
<<li <<" ";
156         }
157         else
158         {
159             char lc = static_cast<char>(li);
160             ProcessOperator(lc,
aosPostfix);
161         }
162     }
163
164     while(!miSta.empty())
165     {
166         aosPostfix
<<(char)miSta.top() <<" ";
167         miSta.pop();
168     }
169     aosPostfix
<<'=' <<endl;
170
171     return 1;
172 }
173
174 int CExprComputer::ComputePostfix(_IN_
istream& aisExpr)
175 {
176     ClearStack();
177
178     int li = 0;
179     bool lbIsChar = false;
180     while( ReadStream(aisExpr, li, lbIsChar) )
181     {
182         // number need immediately output
183         if(!lbIsChar)
184         {
185             miSta.push(li);
186         }
187         else
188         {
189             char lc = static_cast<char>(li);
190             ComputeOperator(lc);
191         }
192     }
193
194     CheckStack();
195     int liResult = miSta.top();
196     miSta.pop();
197
198     DumpStack();
199
200     return liResult;
201 }
202
203 void CExprComputer::ComputeOperator(char ac)
204 {
205     // get lhs and rhs
206     CheckStack();
207     int lilhs = miSta.top();
208     miSta.pop();
209     CheckStack();
210     int lirhs = miSta.top();
211     miSta.pop();
212
213     switch(ac)
214     {
215         case '*':
216         {
217             int liResult = lilhs * lirhs;
218             miSta.push(liResult);
219             break;
220         }
221         case '+':
222         {
223             int liResult = lilhs + lirhs;
224             miSta.push(liResult);
225             break;
226         }
227         default:
228         {
229             cout
<<"Don't support this operator." <<endl;
230             exit(1);
231         }
232     }
233 }
234
235 int CExprComputer::ComputeInfix(_IN_
istream& aisExpr)
236 {
237     stringstream
lss;
238     TransInfix2Postfix(aisExpr,
lss);
239     return ComputePostfix(lss);
240 }

write by 九天雁翎(JTianLing) --
blog.csdn.net/vagrxie

 

分类:  算法 
标签:  C++  reverse polish notation  堆栈  逆波兰记法 

Posted By 九天雁翎 at 九天雁翎的博客 on 2008年12月21日

前一篇: 堆栈的简单C++实现 后一篇: 队列(queue)的链表(list)实现及循环数组(circular array)实现 C++实现