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

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


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

/**
 * 表达式求值系统
 * 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();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值