简单的中缀转后缀并求值的C/C++实现
中缀转后缀
Description
输入一个中缀算术表达式S,S中的操作数为0到9,只含+,-和*,/运算,也可能含有括号(),运算符的计算顺序和实际四则运算的计算顺序相同. 请输出与S等价的后缀表达式,注意输出结果不要含有多余的括号或空格.
Input
输入有多组数据.
每组数据是一个中缀表达式S,S的长度不超过50. 输入的S保证合法,而且不包含多余的空格或制表符.
输入以#号结束.
Output
对于每个中缀表达式,输出转换后的后缀表达式,每个输出占一行.
Sample Input
1
1+2*3
(1-2)/3
#
Sample Output
1
123*+
12-3/
话不多说,直接贴代码,具体分析见上一篇博客
#include <iostream>
#include <stdlib.h>
#include <string>
#include <stack>
using namespace std;
bool isBetter(char a, char b) {
if ((a == '*' || a == '/') && (b == '+' || b == '-')) return true;
return false;
}
int main() {
string input;
while(1) {
cin >> input;
if (input[0] == '#') break; // 判断是否结束
int l = input.size();
stack<char> op;
for (int i = 0; i <= l; i++) {
if (i != l) { // 判断是否到达结尾
// 如果是数字,则直接输出
if (input[i] >= '0' && input[i] <= '9') {
cout << input[i];
} else {
// 如果栈为空或者是左括号,直接入栈
if (op.empty() || input[i] == '(') {
op.push(input[i]);
} else if (input[i] == ')'){
// 如果时右括号,则将栈输出,直到遇到一个左括号
while(!op.empty() && op.top() != '(') {
cout << op.top();
op.pop();
}
op.pop();// 将左括号弹出不输出
} else {
// 如果是运算符,则比较其与栈顶运算符的优先级
while (!op.empty()) {
if (isBetter(input[i], op.top())) { // 如果优先级高,则入栈
break;
} else { // 如果优先级低,则输出栈顶,将当前运算符入栈
if (op.top() != '(') { // 确保栈顶不是左括号,左括号仅在读到右括号时处理
cout << op.top();
op.pop();
} else {
break;
}
}
}
op.push(input[i]); // 将当前运算符入栈
}
}
} else { // 将剩下的操作符输出
while (!op.empty()) {
cout << op.top();
op.pop();
}
}
}
cout << endl;
}
return 0;
}
计算中缀表达式的值
本题目将上面的转换封装为函数,并做了适当的处理以将不同的运算数分开
Description
输入中缀算术表达式S,S中的操作数为非负整数,只含+,-和*,/运算,也可能含有括号(),运算符的计算顺序和实际四则运算的计算顺序相同. 输出表达式S的值. 注意除法运算只取整数部分,例如1/2=0.
Input
输入有多组数据.
每组数据是一个算术表达式S,S的长度不超过100. 输入的S保证合法,而且不包含多余的空格或制表符. S的操作数、中间结果和最终结果都不会超过int类型的范围,也不会出现除数为0的情况.
输入以#号结束.
Output
对于每个算术表达式S,输出S的值,每个输出占一行.
Sample Input
1
478+522
(478+522)*10
1/2-1
#
Sample Output
1
1000
10000
-1
#include <iostream>
#include <stack>
using namespace std;
bool isBetter(char a, char b);
string toPostifix(string input);
int calculate(int x, int y, char t_op);
int main() {
string input, postfix;
while (1) {
// 运用后缀表达式,遇到数字是入栈,遇到运算符时,从栈中取出并弹出两个数进行运算,将其运算结果压入栈中
cin >> input;
if (input[0] == '#') break;
postfix = toPostifix(input); // 转成后缀表达式,用.将数字和操作符间隔开
int ll = postfix.size();
int tmpNum = 0;
int mark = 0; // 用来标记是否输出是单个数字的情况
stack<int> num;
for (int i = 0; i < ll; i++) {
if (postfix[i] == '.') { // 如果读到. 则将读取到的数入栈
if (tmpNum != 0) {
int x = tmpNum;
num.push(x);
tmpNum = 0;
mark = 1;
}
} else {
// 如果遇到的是数字,则逐步将其转成int
if (postfix[i] >= '0' && postfix[i] <= '9') {
tmpNum = tmpNum*10+postfix[i]-'0';
mark = 2;
} else {
// 遇到数字后面没有.而是操作符的情况下,也要将数字提取出来入栈
if (mark == 2) {
int x = tmpNum;
num.push(x);
tmpNum = 0;
mark = 1;
}
// 遇到运算符,计算出新的值,然后入栈
int num1 = num.top();
num.pop();
int num2 = num.top();
num.pop();
int ans = calculate(num2, num1, postfix[i]);
num.push(ans);
}
}
}
if (mark == 2) {
cout << tmpNum << endl;
} else if (!num.empty()) {
cout << num.top() << endl;
}
}
return 0;
}
bool isBetter(char a, char b) {
if ((a == '*' || a == '/') && (b == '+' || b == '-')) return true;
return false;
}
int calculate(int x, int y, char t_op) {
if (t_op == '+') return x+y;
if (t_op == '-') return x-y;
if (t_op == '*') return x*y;
return x/y;
}
string toPostifix(string input) {
string tmp = "";
int l = input.size();
stack<char> op;
for (int i = 0; i <= l; i++) {
if (i != l) { // 判断是否到达结尾
// 如果是数字,则直接输出
if (input[i] >= '0' && input[i] <= '9') {
tmp += input[i];
} else {
tmp += '.';
// 如果栈为空或者是左括号,直接入栈
if (op.empty() || input[i] == '(') {
op.push(input[i]);
} else if (input[i] == ')'){
// 如果时右括号,则将栈输出,直到遇到一个左括号
while(!op.empty() && op.top() != '(') {
tmp += op.top();
op.pop();
}
op.pop();// 将左括号弹出不输出
} else {
// 如果是运算符,则比较其与栈顶运算符的优先级
if (isBetter(input[i], op.top())) { // 如果优先级高,则入栈
op.push(input[i]);
} else { // 如果优先级低,则输出栈顶,将当前运算符入栈
if (op.top() != '(') { // 确保栈顶不是左括号,左括号仅在读到右括号时处理
tmp += op.top();
op.pop();
}
op.push(input[i]); // 将当前运算符入栈
}
}
}
} else { // 将剩下的操作符输出
while (!op.empty()) {
tmp += op.top();
op.pop();
}
}
}
return tmp;
}