栈---逆波兰表达式(RPN)的计算

表达式


表达式 = 操作数(运算对象) + 操作符(运算符) + 分界符
算数表达式有三种表示:(逆波兰表达式又称为后缀表达式)

  • 中缀表达式(infix):<操作数><操作符><操作数>例如:A+B
  • 前缀表达式(prefix):<操作符><操作数><操作数>例如:+AB
  • 后缀表达式(postfix):<操作数><操作数><操作符>例如:AB+

C++中操作符的运算优先级:

优先级 1 2 3 4 5 6 7
操作符 单目一,! *,/% +/- <,<=,>=,> ==,!= && ||

由于中缀表达式有操作符优先级问题,需要使用两个栈才能解决问题,所以一般使用后缀表达式进行计算。
这里写图片描述

详解后缀表达式

A B C D - * + E F / -

步骤 输入项 项类型 操作 栈内容
1 置空栈
2 A 操作数 进栈 A
3 B 操作数 进栈 A B
4 C 操作数 进栈 A B C
5 D 操作数 进栈 A B C D
6 - 操作符 D,C出栈,计算C-D,结果R1进栈 A B R1
7 * 操作符 R1,B出栈,计算B*R1,结果R2进栈 A R2
8 + 操作符 R2,A出栈,计算A+R2,结果R3进栈 R3
9 E 操作数 进栈 R3 E
10 F 操作数 进栈 R3 E F
11 / 操作符 F,E出栈,计算E/F,结果R4进栈 R3 R4
12 - 操作符 R4,R3出栈,计算R3-R4,结果R5进栈 R5

代码实现

#include<stdlib.h>
#include<iostream>
#include<stack>
#include<ctype.h>
using namespace std;


class Calculator{
public:
    //构造函数
    Calculator()
    {}
    void Run();//执行表达式计算---后缀表达式
    void clear();//清除栈空间

private:
    stack<double> s;
    void AddOperand(double value);//操作数进栈
    bool Get2Operand(double& left, double& right);//两个操作数出栈
    void DoOperand(char op);//形成运算指令,进行计算
};


//操作数进栈
void Calculator::AddOperand(double value){
    s.push(value);//将操作数进栈  
}

//两个操作数出栈
bool Calculator::Get2Operand(double& left, double& right){
    if (s.empty() == true)//判断栈是否为空
    {
        cout << "缺少右操作数!" << endl;
        return false;
    }
    right = s.top();
    s.pop();
    if (s.empty() == true)//判断栈是否为空
    {
        cout << "缺少左操作数!" << endl;
        return false;
    }
    left = s.top();
    s.pop();
    return true;
}

//形成运算指令,进行计算
void Calculator::DoOperand(char op){
    double left, right;//待计算的左值和右值
    double result;//计算的结果
    if (Get2Operand(left, right) == true){
        switch (op){
        case '+':
            result = left + right;
            s.push(result);
            break;
        case '-':
            result = left - right;
            s.push(result);
            break;
        case '*':
            result = left * right;
            s.push(result);
            break;
        case '/':
            if (right == 0.0){//除法运算时,右值不能为零
                cerr << "右值为零!" << endl;
                clear();
            }
            else{
                result = left / right;
                s.push(result);
            }
            break;
        default:
            clear();
        }
    }
    else
        clear();
}

//读字符串并求一个后缀表达式的值,以字符'='结束
void Calculator::Run(){
    char ch;
    double newOperand;
    while (cin >> ch, ch != '='){//读入字符
        switch(ch){
        case'+':case'-':case'*':case'/'://判断是否为操作符
            DoOperand(ch);
            break;
        default:
            cin.putback(ch);//将ch放回,以便重新以double类型读入
            cin >> newOperand;
            AddOperand(newOperand);
        }
    }
    if (ch == '=')
    {
        newOperand = s.top();
        cout << newOperand << endl;
    }

}

//清除栈空间
void Calculator::clear(){
    s.empty();
}


int main()
{
    Calculator c;
    while (1){
        cout << "请输入操作数和操作符,以'='结束:" << endl;
        c.Run();
        c.clear();
        fflush(stdin);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_37934101/article/details/80774813