逆波兰(加、减、乘、除、括号)表达式原理及C++代码实现
当我们输入一个数学表达式,是中缀表达式,我们首先转换为后缀表达式(逆波兰表达式),然后再进行求值。
代码思路:
(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++代码实现的更多相关文章
- SQLServer学习笔记<>日期和时间数据的处理(cast转化格式、日期截取、日期的加减)和 case表达式
日期和时间数据的处理. (1)字符串日期 ‘20080301’,这一串为字符串日期,但必须保证为四位的年份,两位的月份,两位的日期.例如,查询订单表日期大于‘20080301’.可以这样写: 1 se ...
- 逆波兰(非与或)表达式原理及C++代码实现
p.p1 { margin: 0; font: 11px Menlo; color: rgba(209, 47, 27, 1); background-color: rgba(255, 255, 25 ...
- Java 实现《编译原理》中间代码生成 -逆波兰式生成与计算 - 程序解析
Java 实现<编译原理>中间代码生成 -逆波兰式生成与计算 - 程序解析 编译原理学习笔记 (一)逆波兰式是什么? 逆波兰式(Reverse Polish notation,RPN,或逆 ...
- leetcode算法学习----逆波兰表达式求值(后缀表达式)
下面题目是LeetCode算法:逆波兰表达式求值(java实现) 逆波兰表达式即后缀表达式. 题目: 有效的运算符包括 +, -, *, / .每个运算对象可以是整数,也可以是另一个逆波兰表达式.同 ...
- noi1696 逆波兰表达式
1696:逆波兰表达式 http://noi.openjudge.cn/ch0303/1696/ 总时间限制: 1000ms 内存限制: 65536kB 描述 逆波兰表达式是一种把运算符前置的算术 ...
- c++实现将表达式转换为逆波兰表达式
https://github.com/Lanying0/lintcode 所属: 数据结构->线性结构->栈 问题: 给定一个表达式字符串数组,返回该表达式的逆波兰表达式(即去掉括号). ...
- java 逆波兰表达式
最近想把这破机 装成WIN7 想想还是算了 ... 反正用的机会也不多. 不过 发现了一些 想念的东西 从前的作业. 从前的记忆. package org.lmz; import java.util ...
- nyoj35——逆波兰表达式
逆波兰表达式又称作后缀表达式,在四则混合运算的程序设计中用到. 例如: 1+2写成后缀表达式就是12+ 4+5*(3-2)的后缀表达式就是4532-*+ 后缀表达式在四则运算中带来了意想不到的方便,在 ...
- [LeetCode] 150. Evaluate Reverse Polish Notation 计算逆波兰表达式
Evaluate the value of an arithmetic expression in Reverse Polish Notation. Valid operators are +, -, ...
随机推荐
- Atcoder Regular Contest 096 C - Everything on It(组合数学)
Atcoder 题面传送门 & 洛谷题面传送门 简单题,由于这场 arc 的 F 是 jxd 作业而我不会做,所以只好来把这场的 E 水掉了. 我们记 \(f(i)\) 为钦定 \(i\) 个 ...
- NOIP2020 模拟赛 B 组 Day6
非常巧妙的一场模拟赛,比较偏向于 Atcoder 的风格,考场上做出了 A .C 两题. A. 礼物购买 排完序后一个个礼物地枚举时间复杂度是\(\Theta(nm)\)的,不能接受.但是注意到,若当 ...
- C7的开机自启动设置
CentOS 7的服务systemctl脚本存放在:/usr/lib/systemd/,有系统(system)和用户(user)之分 系统服务放在/usr/lib/systemd/system [Un ...
- CentOS安装配置Hadoop 1.2.1(伪分布模式)
CentOS安装配置Hadoop1.2.1 1.下载安装文件 下载2个安装文件 JAVA环境:jdk-6u21-linux-i586.bin Hadoop环境:hadoop-1.2.1.tar.gz ...
- 日常Java测试第二段 2021/11/12
第二阶段 package word_show; import java.io.*;import java.util.*;import java.util.Map.Entry; public class ...
- SpringCloud微服务实战——搭建企业级开发框架(三十一):自定义MybatisPlus代码生成器实现前后端代码自动生成
理想的情况下,代码生成可以节省很多重复且没有技术含量的工作量,并且代码生成可以按照统一的代码规范和格式来生成代码,给日常的代码开发提供很大的帮助.但是,代码生成也有其局限性,当牵涉到复杂的业务逻辑 ...
- Learning Spark中文版--第三章--RDD编程(2)
Common Transformations and Actions 本章中,我们浏览了Spark中大多数常见的transformation(转换)和action(开工).在包含特定数据类型的RD ...
- Scala(六)【模式匹配】
目录 一.基本语法 二.匹配固定值 三.守卫 四.匹配类型 五.匹配集合 1.Array 2.List 3.元祖 4.对象和样例类 六.偏函数 七.赋值匹配 八.for循环匹配 一.基本语法 在匹配某 ...
- 【leetcode】122.Best Time to Buy and Sell Stock II(股票问题)
You are given an integer array prices where prices[i] is the price of a given stock on the ith day. ...
- 【STM8】SPI通讯
这篇内容有点长,如果有人想透过我的博客学习STM8的SPI,那是我的荣幸 首先我要先说大纲,这样大家心里比较有底,可以把精力都用在SPI理解上 [SPI初步介绍]:介绍SPI如何接线.名称解释.通讯注 ...