通过入栈出栈实现数学表达式的计算

原创 2016年02月25日 09:30:32
#include <iostream>
#include <stack>
#include <string>
#include <cstring>
using namespace std;

class Exp {
    stack<char> ops; // 运算符栈
    stack<double> ds; // 数据栈
    double v, lh, rh; // 计算结果和临时变量
    char op; // 读取运算符
public:
    double calinput() { //读取并计算表达式,直到结束为止
        do {
            readdata(); //读取数据
            skipspace(); //跳过空白
        } while (readop()); //读取运算符
        calremain(); //处理栈中剩余的运算符
        return v;
    }
    //读取数据
    void readdata() {
        while (!(cin >> v)) { //读取数据失败,应该是左括号
            cin.clear();
            cin >> op; //读取必须是左括号
            if (op != '(') {
                throw string("在该出现数值的地方遇到了") + op;
            }
            ops.push(op);
        }
        ds.push(v);
    }
    //跳过空格
    void skipspace() {
        //cin.peek()查看不取走
        while (cin.peek() == ' ' || cin.peek() == '\t') {
            cin.ignore();
        }
    }
    //读取运算符,可能遇到右括号')'或者换行符'\n'
    bool readop() {
        while ((op = cin.get()) == ')') {
            while (ops.top() != '(') { //找栈里左括号'('
                rh = ds.top(); //从栈中取出右操作数
                ds.pop();
                lh = ds.top(); //从栈中取出左操作数
                ds.pop();
                ds.push(cal(lh, ops.top(), rh)); //取出运算符,计算左右操作数
                ops.pop();
            }
            ops.pop(); //丢弃找到的左括号'('
        }
        if (op == '\n') {
            return false;
        }
        if (strchr("+-*/", op) == NULL) { //无效运算符
            throw string("无效运算符") + op;
        }
        while (!ops.empty() && ops.top() != '(' && !prior(op, ops.top())) {
            rh = ds.top();
            ds.pop();
            lh = ds.top();
            ds.pop();
            ds.push(cal(lh, ops.top(), rh));
            ops.pop();
        }
        ops.push(op);
        return true;
    }
    void calremain() {
        while (!ops.empty()) {
            rh = ds.top();
            ds.pop();
            lh = ds.top();
            ds.pop();
            ds.push(cal(lh, ops.top(), rh));
            ops.pop();
        }
        if (ds.size() != 1) {
            throw string("无效的表达式");
        }
        v = ds.top();
        ds.pop();
    }
    double cal(double lh, char op, double rh) {
        return op == '+' ? lh + rh : op == '-' ? lh - rh :
                op == '*' ? lh * rh : lh / rh;
    }
    bool prior(char o1, char o2) {
        return (o1 != '+' && o1 != '-' && o2 != '*' && o2 != '/');
    }
};

int main(int argc, char** argv) {
    Exp e;
    try {
        cout << e.calinput() << endl;
    } catch (const string& e) {
        cout << e << endl;
    }
    return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

C#.NET窗体入栈出栈

  • 2015-12-13 17:01
  • 905B
  • 下载

Qt计算器开发(一):后缀表达式实现完整数学表达式的计算

相信学过数据结构的人都听说过后缀表达式,就是在学习栈的时候。相信大家也都用过计算器windows里面的calc。但是有没发现它只能单步计算,而不能一次计算一个表达式。后缀表达式就有了用武之地,可以一次...

数据结构之栈与队列数学表达式的求值

数学表达式的计算     课本上使用c去实现个位数字的加减乘除,于是我将它扩展到了浮点数的四则运算   用了逆波兰表达式,具体怎么算还是百度一下吧,我的表达能力肯定不如百度啦   另外我终于去学...

poj1363 入栈出栈模拟

Rails Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 25009...

栈、堆内存到底是如何申请的,方法是如何入栈出栈的——内存结构理解学习

对于软件开发者而言,理解和熟悉计算机内存知识是最为基础的了。今天我就来翻翻旧账,回顾回顾看看我有哪些点遗漏了,在此共同学习。 提起内存,我们常常想到三个区域: 1,静态区,静态变量 static va...
  • hnulwt
  • hnulwt
  • 2015-01-23 19:42
  • 2825

入栈出栈规律·

相信大家都做过类似这样的题目: 已知入栈序列为:1 2 3 4 5,这5个数一次入栈,出栈顺序、时机任意。 则下列可能的出栈序列不正确的是() A 1 2 3 4 5 B 3 2 1 5 4 ...

简单的栈操作的模拟,入栈出栈

杭电ACM 2014暑期集训队——选拔安排~ Train Problem I Time Limit: 2000/1000 MS (Java/Others)    Memory ...

华为机试 计算加减乘除数学表达式的结果

#include #include #include //是const char* 问题不能改成char* 指针的问题 华为机试 int cal(int len,const ch...

栈---定义、应用(递归、后缀表达式实现数学表达式求值)

一、定义栈是限定仅在表尾进行插入和删除操作的线性表。因此,栈的表尾端称为栈顶;表头端称为栈底。不含任何数据元素的栈称为空栈。栈又称为后进先出(Last In First Out)的线性表,简称LIF0...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)