中缀表达式转后缀表达式并求值
代码都是自解释的,重要函数也有注释,我就不多说了。
/**
* 表达式求值系统
* A 类题:表达式求值系统
* 实现一个基本的表达式求值系统,要求从键盘读入带有括号的中
* 缀表达式,要求首先判断括号是否匹配,如果括号匹配表达式合法,
* 再将中缀表达式转换为后缀表达式,并计算和输出表达式的值。对常
* 见输入错误的判断,比如:括号错误、非法字符、运算符号错误、除
* 数为零等错误情况。
* (1) 使用自己实现的栈或使用 STL 中的栈;
* (2) 对输入的中缀表达式进行括号匹配判断,匹配输出 YES,否则输出 NO;
* (3) 使用栈将中缀表达式转换为后缀表达式,并输出后缀表达式;
* (4) 对后缀表达式进行计算并输出;
*/
#ifdef LOCAL
#include <fstream>
#endif // LOCAL
#include <iostream>
#include <stack>
#include <string>
#include <cctype>
#include <cstring>
#include <cstdio>
#include <cstdlib>
using namespace std;
const int MAXN = 2000;
const char operators[] = "()+-/*";
stack<char> s; // operators stack.
void readDataAndDeal();
bool match(string &infixStr);
bool isOperator(char ch);
void convertToSuffix(const string &source, string &dest);
int getPriority(char ch);
double calculate(const string &suffixStr);
int main() {
#ifdef LOCAL
freopen("A4in.txt", "r", stdin);
#endif // LOCAL
readDataAndDeal();
return 0;
}
/**
* read the data and deal with them.
*/
void readDataAndDeal() {
char temp[MAXN];
fgets(temp, MAXN, stdin);
string infixStr(temp), suffixStr;
if (match(infixStr))
printf("YES\n");
else {
printf("NO\n");
return;
}
convertToSuffix(infixStr, suffixStr);
printf("%s\n", suffixStr.c_str());
printf("%f\n", calculate(suffixStr));
}
/**
* If infixStr[i] is '(': push stack.
* If infixStr[i] is ')': pop stack.
* If the stack isn't empty: match failed.
* operators[0] = '(' , operators[1] = ')'
* @param infixStr - the infix string.
* @return bool - true if infix string is valid.
*/
bool match(string &infixStr) {
while (!s.empty())
s.pop();
for (size_t i = 0; i < infixStr.size(); i++) {
if (isspace(infixStr[i])) continue;
if (isdigit(infixStr[i]) || isOperator(infixStr[i])) {
if (infixStr[i] == operators[0])
s.push(operators[0]);
else if (infixStr[i] == operators[1]) {
if (!s.empty())
s.pop();
else
return false;
}
} else
return false;
}
if (!s.empty())
return false;
return true;
}
/**
* Judge the ch is '+', '-', '*', '/', '(', ')' or not.
* @param ch - the judge char.
* @return true if is operators.
*/
bool isOperator(char ch) {
for (size_t i = 0; i < sizeof(operators) / sizeof(char); i++) {
if (ch == operators[i])
return true;
}
return false;
}
/**
* @param source - infix string
* @param dest - suffix string
* (1)Read an infix expression from left to right.
* (2)If it's an operator, append to the dest string with space.
* (3)If it's operator '(', push it to stack.
* (4)If it's operator ')', pop the stack and append to dest string until
* the top element is '(', remove the '('.
* (5)If it is not a bracket operator, compare their priorities with the stack top elements:
* (a)If hight than top element, push it to stack.
* (b)If low or equal than top element, append it to dest until the top
* element is '(' or the stack is empty.
* (6)If the stack isn't empty, pop and append it to dest until stack empty.
*/
void convertToSuffix(const string &source, string &dest) {
while (!s.empty()) //clear stack
s.pop();
bool addSpace = false;
for (size_t i = 0; i < source.size(); i++) {
if (isspace(source[i])) continue;
if (isdigit(source[i])) {
if (addSpace) {
dest += ' ';
addSpace = false;
}
dest += source[i];
}
else if (source[i] == '(')
s.push('(');
else if (source[i] == ')') {
while (s.top() != '(') {
dest = dest + ' ' + s.top();
s.pop();
}
s.pop();// delete the '('
} else {
addSpace = true;
while (!s.empty()) {
int oldChar = getPriority(s.top());
int newChar = getPriority(source[i]);
if (oldChar < newChar || s.top() == '(') {
s.push(source[i]);
break;
}
else {
dest = dest + ' ' + s.top();
s.pop();
}
}
if(s.empty())s.push(source[i]);
}
}
while (!s.empty()) {
dest = dest + ' ' + s.top();
s.pop();
}
}
/**
* @param ch - the operator char
* @return digit - the priority of operator char
*/
int getPriority(char ch) {
if (ch == '+' || ch == '-')
return 0;
else
return 1;
}
/**
* @param suffixStr - the suffix string.
* @return double - the calculate result.
* (1)If the element is number, push to stack.
* (2)If the element is operator , pop two elements with a and b, calculate them.
*/
double calculate(const string &suffixStr) {
stack<double> s;
char ss[MAXN];
strcpy(ss, suffixStr.c_str());
char *p = NULL;
p = strtok(ss, " ");
while (p != NULL) {
//printf("%s\n", p);
if (isOperator(p[0])) {
double b = s.top();
s.pop();
double a = s.top();
s.pop();
switch(p[0]) {
case '+': s.push(a + b); break;
case '-': s.push(a - b); break;
case '*': s.push(a * b); break;
case '/': {
if (b == 0) {
printf("you can't div by zero!\n");
return 0;
}else {
s.push(a / b);
break;
}
}
}
} else {
s.push(strtod(p, NULL));
}
p = strtok(NULL, " ");
}
return s.top();
}