中缀表达式

Posted friedcoder

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了中缀表达式相关的知识,希望对你有一定的参考价值。

不含括号的中缀表达式

代码实现

//直接计算中缀表达式
//不含括号
#include<iostream>
#include<stack>
#include<string>

using namespace std;

//运算符号优先级比较
//加减为低级运算,乘除是高级运算;先算乘除
//return 1 means can calculate, else can not.
int getPriority( stack<char> operators )
{
    if( !operators.empty()  && ( operators.top() == '*' || operators.top() == '/') ){
        return 1;
    }

    return 0;
}


//输入操作符栈 和 操作数栈 进行计算
void calculate(stack<double> &operands, stack<char> &operators)
{
    double op1, op2, res;
    char operation;

    op2 = operands.top();
    operands.pop();
    op1 = operands.top();
    operands.pop();

    operation = operators.top();
    operators.pop();

    switch( operation ){
        case '+':
            res = op1 + op2;
            break;
        case '-':
            res = op1 - op2;    //对顺序有要求
            break;
        case '*':
            res = op1 * op2;
            break;
        case '/':
            res = op1 / op2;    //这个顺序不能反
            break;
    
    }

    //cout << op1 << operation << op2 << "=" << res << endl;    //test
    operands.push(res);

}


int main()
{
    stack<double> operands; //除法运算可能会出现小数
    stack<char> operators;

    string formula;
    string number;

    const string numbers = "0123456789";
    const string operation = "+-*/";

    cin >> formula;
    for( string::iterator c = formula.begin();  c != formula.end();  c++ ){

        //处理数字
        if( numbers.find(*c) != string::npos ){
            while( numbers.find(*c) != string::npos ){
                number += *c;
                c++;
            } 
            operands.push( stod(number) );
            number.clear();

               //读完最后一个数字
            if ( c == formula.end() ){
                if( getPriority(operators) == 1 ){  //最后一个操作符可能是乘除
                    calculate(operands, operators);
                }
                break;  
            }
        }

        //calculate, 先算乘除
        if( operation.find(*c) != string::npos ){
            if ( getPriority(operators)  ==  1 ){
                calculate( operands, operators );
            }
            operators.push((*c));
        }
    }


    //处理剩余的加减
    while( !operators.empty() ){
        char operation = operators.top();

        //减法有顺序要求;1-2+3,先执行1-2=-1,再执行-1+3
        if( operation == '+' ){
            operators.pop();
            if( !operators.empty()  &&  operators.top() == '-' ){
                double tmp = operands.top();
                operands.pop();

                calculate( operands, operators );

                operators.push(operation);
                operands.push(tmp);
            }   
            else{
                operators.push(operation);
                calculate( operands, operators );
            }

        }
        else{
            calculate( operands, operators );
        }

    }
    
    cout << formula << " = " << operands.top() << endl;
    return 0;
}

含括号的中缀表达式代码实现

//直接计算中缀表达式
//含括号
#include<iostream>
#include<deque>
#include<string>

using namespace std;


//运算符号优先级比较
//return 1 means can calculator, else can not.
int getPriority( deque<char> operators )
{
    if( !operators.empty()  && ( operators.back() == '*' || operators.back() == '/') ){
        return 1;
    }

    return 0;
}


double calculate( double op1, double op2, char operation )
{
    double res;

    switch( operation ){
        case '+':
            res = op1 + op2;
            break;
        case '-':
            res = op1 - op2;    //对顺序有要求
            break;
        case '*':
            res = op1 * op2;
            break;
        case '/':
            res = op1 / op2;    //这个顺序不能反
            break;
    }

    //cout << op1 << operation << op2 << "=" << res << endl;    //test

    return res;
}

void calculator(deque<double> &operands, deque<char> &operators)
{
    double op1, op2, res;
    char operation;

    operation = operators.back();
    operators.pop_back();

    //这个糟糕的顺序
    if( operation == '-' ){
        op1 = operands.back();
        operands.pop_back();
        op2 = operands.back();
        operands.pop_back();
    }else{
        op2 = operands.back();
        operands.pop_back();
        op1 = operands.back();
        operands.pop_back();
    }


    res = calculate( op1, op2, operation );

    operands.push_back(res);
}




int main()
{
    deque<double> operands; //除法运算可能会出现小数; 使用deque,比栈更灵活
    deque<char> operators;

    string formula;
    string number;

    const string numbers = "0123456789";
    const string Operation = "+-*/";

    cin >> formula;
    for( string::iterator c = formula.begin();  c != formula.end();  c++ ){

        //处理数字
        if( numbers.find(*c) != string::npos ){
            while( numbers.find(*c) != string::npos ){
                number += *c;
                c++;
            } 
            operands.push_back( stod(number) );
            number.clear();

               //读完最后一个数字
            if ( c == formula.end() ){
                if( getPriority(operators) == 1 ){  //最后一个可能是乘除
                    calculator(operands, operators);
                }
                break;  
            }
        }

        //处理 + - * /
        if( Operation.find(*c) != string::npos ){
            //calculator, 先算乘除
            if ( getPriority(operators)  ==  1 ){
                calculator( operands, operators );
            }
            operators.push_back((*c));
        }
        //处理括号
        else{
            if( *c == '(' ){
                operators.push_back((*c));
            }
            //遇到)”时,算出()内算式的值
            else{   
                //)前面可能是乘除
                if(  getPriority(operators) == 1 ){
                    calculator(operands, operators);
                }

                //此时括号内已经没有乘除
                deque<double> tmp_oprands;
                deque<char> tmp_operators;
                //把()内的算式pop到新的栈
                while( operators.back() != '(' ){
                    tmp_oprands.push_back(operands.back());
                    operands.pop_back();
                    
                    tmp_operators.push_back(operators.back());
                    operators.pop_back();
                }
                tmp_oprands.push_back(operands.back());
                operands.pop_back();
                operators.pop_back();   //弹出“(”
                
                while(!tmp_operators.empty()){  //计算括号内的算式
                    calculator( tmp_oprands, tmp_operators );
                }

                operands.push_back( tmp_oprands.back() );   //push结果
                tmp_oprands.pop_back();

            }
        
        }
    }


    //处理剩余的加减
    double op1, op2, res;
    char operation;
    while( !operators.empty() ){

        //因为前面使用的是deque结构而不是stack,所以这里可以从栈底开始读取
        //(考虑到减法运算过程中的y顺序要求)
        op1 = operands.front();
        operands.pop_front();
        op2 = operands.front();
        operands.pop_front();

        operation = operators.front();
        operators.pop_front();

        res = calculate( op1, op2, operation);

        operands.push_front(res);
    }
    
    cout << formula << " = " << operands.back() << endl;
    return 0;
}

改进

前面的算法将加减与乘除分开处理,导致后面运算加减的时候还要考虑减法的运算顺序问题,变得麻烦了。
下面是改进后的代码

以上是关于中缀表达式的主要内容,如果未能解决你的问题,请参考以下文章

中缀表达式

中缀表达式

中缀表达式转后缀表达式(Java代码实现)

中缀表达式求值的思路分析与代码实现

中缀表达式求值的思路分析与代码实现

栈实现综合计算器(中缀表达式),前缀,中缀,后缀表达式,逆波兰计算器