当我们输入一个数学表达式,是中缀表达式,我们首先转换为后缀表达式(逆波兰表达式),然后再进行求值。

代码思路:

(1)首先对输入的中缀表达式合法性进行判断,bool isStringLegal(const char* str); 函数实现。

(2)然后把中缀表达式转换为后缀表达式。

(3)根据后缀表达式求出结果,double getTheResult(vector<string> &vec);函数实现。

注意:表达式的运算符可以输入 加、减、乘、除、括号,输入的数据为整形数据,计算结果为double型数据。

  1 #include <iostream>
2 #include <math.h>
3 #include <map>
4 #include <vector>
5 #include <string.h>
6 #include <memory>
7 #include <string>
8 #include <stdio.h>
9 #include <stack>
10 #include <stdlib.h>
11
12 using namespace std;
13
14 #define MAX_STRING_LENGTH 100
15
16 /* 解析当前的整形数据,并把整形数据转换为string型 */
17 string analyData(const char* str, int &i);
18
19 /* 根据逆波兰表达式求表达式的值 */
20 double getTheResult(vector<string> &vec);
21
22 /* 判断该字符是否是 + - * / ( ) */
23 bool isCalChar(const char ch);
24
25 /* 判断输入的中缀表达式是否合法 */
26 bool isStringLegal(const char* str);
27
28
29
30 /* 解析当前的整形数据,并把整形数据转换为string型 */
31 string analyData(const char* str, int &i)
32 {
33 int temp = i++;
34 while(str[i] >= '0' && str[i] <= '9' && str[i] != '\0')
35 {
36 i++;
37 }
38
39 string s(str+temp,str+i);
40
41 return s;
42 }
43
44 /* 根据逆波兰表达式求表达式的值 */
45 double getTheResult(vector<string> &vec)
46 {
47 vector<string>::iterator it;
48 stack<double> sta;
49
50 string strTemp;
51 double d = 0, d1 = 0, d2 = 0;
52
53 for(it = vec.begin(); it != vec.end(); it++)
54 {
55 strTemp = (*it);
56
57 if(strTemp == "+")
58 {
59 d1 = sta.top();
60 sta.pop();
61
62 d2 = sta.top();
63 sta.pop();
64
65 d = d1 + d2;
66 sta.push(d);
67 }
68 else if(strTemp == "-")
69 {
70 d1 = sta.top();
71 sta.pop();
72
73 d2 = sta.top();
74 sta.pop();
75
76 d = d2 - d1;
77 sta.push(d);
78 }
79 else if(strTemp == "*")
80 {
81 d1 = sta.top();
82 sta.pop();
83
84 d2 = sta.top();
85 sta.pop();
86
87 d = d2 * d1;
88 sta.push(d);
89 }
90 else if(strTemp == "/")
91 {
92 d1 = sta.top();
93 sta.pop();
94
95 d2 = sta.top();
96 sta.pop();
97
98 d = d2 / d1;
99 sta.push(d);
100 }
101 else
102 {
103 const char *p = strTemp.c_str();
104 d = atoi(p);
105 sta.push(d);
106 }
107 }
108 return sta.top();
109 }
110
111 /* 判断该字符是否是 + - * / ( ) */
112 bool isCalChar(const char ch)
113 {
114 if(ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '(' || ch == ')')
115 {
116 return true;
117 }
118
119 return false;
120 }
121 /* 判断输入的中缀表达式是否合法 */
122 bool isStringLegal(const char* str)
123 {
124 /* 判断是否是空串 */
125 if(NULL == str)
126 {
127 return false;
128 }
129
130 int len = strlen(str);
131 int i = 0;
132 int flag = 0;
133
134 /* 字符串的开头和末尾是否是数字 */
135 if(str[0] > '9' || str[0] < '0' || str[len-1] > '9' || str[len-1] < '0')
136 {
137 return false;
138 }
139
140
141 for(i = 0; str[i] != '\0'; i++)
142 {
143 /* 是否有除了加减乘除括号之外的字符 */
144 if(isCalChar(str[i]) == false)
145 {
146 return false;
147 }
148
149 /* 判断是否有两个连续的符号 */
150 if(i < len-1 && isCalChar(str[i]) == true)
151 {
152 if(isCalChar(str[i+1]) == true)
153 {
154 return false;
155 }
156
157 }
158
159 /* 判断括号是否成对 */
160 if(str[i] == '(')
161 {
162 flag++;
163 }
164 else if(str[i] == ')')
165 {
166 flag--;
167 }
168
169 /* 判断是否出现 )( 这样的情况 */
170 if(flag < 0)
171 {
172 return false;
173 }
174 }
175
176 /* 判断括号是否匹配 */
177 if(flag != 0)
178 {
179 return false;
180 }
181
182 return true;
183 }
184
185 int main(void)
186 {
187 char str[MAX_STRING_LENGTH] = {0};
188 int i = 0;
189 string data;
190
191 /* 存放运算符表达式的栈 */
192 stack<char> oper_char;
193
194 /* 存放后缀表达式 */
195 vector<string> post_str;
196
197 /* 输入中缀的表达式 */
198 gets(str);
199
200 /* 判断输入的中缀表达式是否合法 */
201 if(isStringLegal(str) != true)
202 {
203 cout << "This expression is not legal." << endl;
204 }
205 else
206 {
207 /* 将中缀表达式转换为后缀表达式 */
208 for(i = 0; str[i] != '\0'; i++)
209 {
210 /* 如果该字符为数字,解析该数字,并压入栈 */
211 if(str[i] >= '0' && str[i] <= '9')
212 {
213 data = analyData(str,i);
214 post_str.push_back(data);
215 i--;
216 }
217 else if(str[i] == '(')
218 {
219 oper_char.push(str[i]);
220 }
221 else if(str[i] == ')')
222 {
223 char chtemp[2] = {0};
224
225 chtemp[0] = oper_char.top();
226
227 while(chtemp[0] != '(')
228 {
229 string strtemp(chtemp);
230 post_str.push_back(strtemp);
231 oper_char.pop();
232
233 chtemp[0] = oper_char.top();
234 }
235 oper_char.pop();
236 }
237 else if(str[i] == '+' || str[i] == '-')
238 {
239 char chtemp[2] = {0};
240
241 /* 全部出栈,但是碰到 '('就要停止出栈 */
242 while(oper_char.size() != 0)
243 {
244 chtemp[0] = oper_char.top();
245 if(chtemp[0] == '(')
246 {
247 break;
248 }
249
250 oper_char.pop();
251
252 string strtemp(chtemp);
253 post_str.push_back(strtemp);
254 }
255
256 /*将当前的表达式符号入栈*/
257 oper_char.push(str[i]);
258 }
259 else if(str[i] == '*' || str[i] == '/')
260 {
261 char chtemp[2] = {0};
262 while(oper_char.size() != 0)
263 {
264 chtemp[0] = oper_char.top();
265 if(chtemp[0] == '(' || chtemp[0] == '+' || chtemp[0] == '-')
266 {
267 break;
268 }
269 else
270 {
271 oper_char.pop();
272
273 string strtemp(chtemp);
274 post_str.push_back(strtemp);
275 }
276 }
277
278 /*将当前的表达式符号入栈*/
279 oper_char.push(str[i]);
280 }
281 }
282
283 /* 存放表达式的栈可能还有数据 */
284 while(!oper_char.empty())
285 {
286 char chtemp[2] = {0};
287 chtemp[0] = oper_char.top();
288 oper_char.pop();
289
290 string strtemp(chtemp);
291 post_str.push_back(strtemp);
292 }
293
294 /* 把逆波兰表达式求值 */
295 cout << getTheResult(post_str) << endl;
296 }
297
298 return 0;
299 }

逆波兰(加、减、乘、除、括号)表达式原理及C++代码实现的更多相关文章

  1. SQLServer学习笔记<>日期和时间数据的处理(cast转化格式、日期截取、日期的加减)和 case表达式

    日期和时间数据的处理. (1)字符串日期 ‘20080301’,这一串为字符串日期,但必须保证为四位的年份,两位的月份,两位的日期.例如,查询订单表日期大于‘20080301’.可以这样写: 1 se ...

  2. 逆波兰(非与或)表达式原理及C++代码实现

    p.p1 { margin: 0; font: 11px Menlo; color: rgba(209, 47, 27, 1); background-color: rgba(255, 255, 25 ...

  3. Java 实现《编译原理》中间代码生成 -逆波兰式生成与计算 - 程序解析

    Java 实现<编译原理>中间代码生成 -逆波兰式生成与计算 - 程序解析 编译原理学习笔记 (一)逆波兰式是什么? 逆波兰式(Reverse Polish notation,RPN,或逆 ...

  4. leetcode算法学习----逆波兰表达式求值(后缀表达式)

    下面题目是LeetCode算法:逆波兰表达式求值(java实现) 逆波兰表达式即后缀表达式. 题目:  有效的运算符包括 +, -, *, / .每个运算对象可以是整数,也可以是另一个逆波兰表达式.同 ...

  5. noi1696 逆波兰表达式

    1696:逆波兰表达式 http://noi.openjudge.cn/ch0303/1696/ 总时间限制:  1000ms 内存限制:  65536kB 描述 逆波兰表达式是一种把运算符前置的算术 ...

  6. c++实现将表达式转换为逆波兰表达式

    https://github.com/Lanying0/lintcode 所属: 数据结构->线性结构->栈 问题: 给定一个表达式字符串数组,返回该表达式的逆波兰表达式(即去掉括号). ...

  7. java 逆波兰表达式

    最近想把这破机 装成WIN7 想想还是算了 ...  反正用的机会也不多. 不过 发现了一些 想念的东西 从前的作业. 从前的记忆. package org.lmz; import java.util ...

  8. nyoj35——逆波兰表达式

    逆波兰表达式又称作后缀表达式,在四则混合运算的程序设计中用到. 例如: 1+2写成后缀表达式就是12+ 4+5*(3-2)的后缀表达式就是4532-*+ 后缀表达式在四则运算中带来了意想不到的方便,在 ...

  9. [LeetCode] 150. Evaluate Reverse Polish Notation 计算逆波兰表达式

    Evaluate the value of an arithmetic expression in Reverse Polish Notation. Valid operators are +, -, ...

随机推荐

  1. 监听浏览器tab切换

    监听浏览器切屏 为了完成验证用户在切换浏览器tab时进行登录再次认证需求需要监听浏览器切换窗口 if (document.hidden !== undefined) { document.addEve ...

  2. 有限元边界 Dirichlet 条件处理

    参考自百度文档,这里只考虑 Dirichlet 边界条件情况. 有限元法基本方法就是是构造线性方程组 \[\begin{equation} Au = f \end{equation}\] 进行求解.其 ...

  3. [R报错] Kruskal-wallis test 所有组的层次都必需是有限的

    做了个两组间的Kruskal-wallis检验,出现如下错误: 对应的英文版本错误为: All group levels must be finite is.finite(data$type)一下果然 ...

  4. 基于MS SQL Server的数据库学习安排

    序号 分类 学习内容 目标/要求 方式 学时 考核 参考资料 1 基础知识 数据库理论 理解数据库基本理论 面授 1 能阐述元素.数据记录.数据表.数据库的基本概念T-SQL语法要求 https:// ...

  5. C#gridview颜色提示

    OnRowCreated="gridStatistic_RowCreated private void FillUI() { gridStatistic.DataSource = dtSta ...

  6. day17 常用模块的应用

    day17 常用模块的应用 老师博客园地址:https://www.cnblogs.com/linhaifeng/articles/6384466.html#_label11 一.time与datet ...

  7. Learning Spark中文版--第六章--Spark高级编程(2)

    Working on a Per-Partition Basis(基于分区的操作) 以每个分区为基础处理数据使我们可以避免为每个数据项重做配置工作.如打开数据库连接或者创建随机数生成器这样的操作,我们 ...

  8. HTTP 之 options预请求

    一.HTTP一共有八种常见请求方法 get:参数在url上,浏览器长度有限制,不安全 post:参数不可见,长度不受限制 put:上传最新内容到指定位置 delete:删除请求的url所表示的资源 h ...

  9. Can we access global variable if there is a local variable with same name?

    In C, we cannot access a global variable if we have a local variable with same name, but it is possi ...

  10. Linux:$i 和 ${i}区别

    例如你要把有个变量的值和其他字符串连接起来,就需要用到{},以明示{}中的是一个变量. 例如: export var1=ABC export var2=var1=${var1} echo $var2 ...