逆波兰(加、减、乘、除、括号)表达式原理及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 +, -, ...
随机推荐
- 2021-2-3-利用anaconda+prefetch+aspera从NCBI的SRA数据库中下载原始测序数据
目录 1.Conda连接不上镜像源问题 2. aspera不能再独立使用 3.使用prefetch搭配aspera 4. prefetch下载方法 记录下下载过程,为自己和后人避坑. 1.Conda连 ...
- expr判断是否为整数
判断一个变量值或字符串是否为整数 原理:利用expr计算时变量或字符串必须为整数的规则,把变量和一个整数(非零) 相加,判断命令返回是否为0,0--成功为整数 #!/bin/bash expr $1 ...
- expr判断文件名以固定格式结尾
#!/bin/bash if expr "$1" : ".*\.sh" &>/dev/null then echo "okok" ...
- tabix 操作VCF文件
tabix 可以对NGS分析中常见格式的文件建立索引,从而加快访问速度,不仅支持VCF文件,还支持BED, GFF,SAM等格式. 下载地址: 1 https://sourceforge.net/pr ...
- 【7】基于NGS检测体系变异解读和数据库介绍
目录 解读相关专业术语 体系变异解读规则 体系变异和用药解读流程 主要数据库介绍 解读相关专业术语 2个概念:胚系.体系突变 4种变异类型:SNV.Indel.融合/SV(大的易位/倒位/缺失).CN ...
- 通过mac地址确认二层交换机某个端口下接的终端设备IP
正常来说,二层交换机主要是通过mac地址进行通信的,这就导致我们无法直接通过arp表来确认交换机端口下终端设备的IP: 但我们仍然能通过查找二层交换机端口下学习到的mac地址,然后通过对照三层核心交换 ...
- 35-Remove Element
Remove Element My Submissions QuestionEditorial Solution Total Accepted: 115367 Total Submissions: 3 ...
- 基于 芯片 nordic 52832 rtt 调试(Mac 电脑)
代码配置 // <e> NRF_LOG_BACKEND_SERIAL_USES_UART - If enabled data is printed over UART //======== ...
- KeepAlived双主模式高可用集群
keepalived是vrrp协议的实现,原生设计目的是为了高可用ipvs服务,keepalived能够配置文件中的定义生成ipvs规则,并能够对各RS的健康状态进行检测:通过共用的虚拟IP地址对外提 ...
- Swift Storyboard找不到类文件
Swift语言引入了Module概念,在通过关键字@objc(类名)做转换的时候,由于Storyboard没有及时更新Module属性,会导致如下两种类型错误: 1 用@objc(类名)标记的Swif ...