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

代码思路:

(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. Atcoder Regular Contest 096 C - Everything on It(组合数学)

    Atcoder 题面传送门 & 洛谷题面传送门 简单题,由于这场 arc 的 F 是 jxd 作业而我不会做,所以只好来把这场的 E 水掉了. 我们记 \(f(i)\) 为钦定 \(i\) 个 ...

  2. NOIP2020 模拟赛 B 组 Day6

    非常巧妙的一场模拟赛,比较偏向于 Atcoder 的风格,考场上做出了 A .C 两题. A. 礼物购买 排完序后一个个礼物地枚举时间复杂度是\(\Theta(nm)\)的,不能接受.但是注意到,若当 ...

  3. C7的开机自启动设置

    CentOS 7的服务systemctl脚本存放在:/usr/lib/systemd/,有系统(system)和用户(user)之分 系统服务放在/usr/lib/systemd/system [Un ...

  4. CentOS安装配置Hadoop 1.2.1(伪分布模式)

    CentOS安装配置Hadoop1.2.1 1.下载安装文件 下载2个安装文件 JAVA环境:jdk-6u21-linux-i586.bin Hadoop环境:hadoop-1.2.1.tar.gz ...

  5. 日常Java测试第二段 2021/11/12

    第二阶段 package word_show; import java.io.*;import java.util.*;import java.util.Map.Entry; public class ...

  6. SpringCloud微服务实战——搭建企业级开发框架(三十一):自定义MybatisPlus代码生成器实现前后端代码自动生成

      理想的情况下,代码生成可以节省很多重复且没有技术含量的工作量,并且代码生成可以按照统一的代码规范和格式来生成代码,给日常的代码开发提供很大的帮助.但是,代码生成也有其局限性,当牵涉到复杂的业务逻辑 ...

  7. Learning Spark中文版--第三章--RDD编程(2)

    Common Transformations and Actions   本章中,我们浏览了Spark中大多数常见的transformation(转换)和action(开工).在包含特定数据类型的RD ...

  8. Scala(六)【模式匹配】

    目录 一.基本语法 二.匹配固定值 三.守卫 四.匹配类型 五.匹配集合 1.Array 2.List 3.元祖 4.对象和样例类 六.偏函数 七.赋值匹配 八.for循环匹配 一.基本语法 在匹配某 ...

  9. 【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. ...

  10. 【STM8】SPI通讯

    这篇内容有点长,如果有人想透过我的博客学习STM8的SPI,那是我的荣幸 首先我要先说大纲,这样大家心里比较有底,可以把精力都用在SPI理解上 [SPI初步介绍]:介绍SPI如何接线.名称解释.通讯注 ...