中缀表达式转后缀表达式并求值


  代码都是自解释的,重要函数也有注释,我就不多说了。

/** * 表达式求值系统 * 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 * 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. * 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();
}