昨天写了一个文章,中缀表达式转后缀表达式,现在就用这个方式再实现计算器……
表达式一旦转换成后缀表达式再进行计算就简单的不得了。遇到一个符号就弹出离他最近的两个操作数然后进行这个操作符指定的运算就ok了……运算完成后压栈继续扫描,依次重复……等到操作符没有了。所有的运算也就结束了。结果也就出来了……不必再判断优先级的什么的了。括号什么的也一并省略……爽吧。
其实在中缀转后缀的时候就可以进行计算,表达式扫描完成,计算完成。
把昨天的代码直接复制……修改……
opt.push('#'); char ch = opt.top(); // 表达式扫描完后把栈中剩余的操作符全部输出 |
看到没有和昨天的代码几乎没有区别,只是在昨天 输出的地方换成了运算 OP(const char &ch); 完成运算
要明白一点。表达式扫描完成,有可能操作符是压栈了而未进行运行,(这由具体的表达式决定),因此最后要把操作符栈弹空,完成全部的运算……则此时操作数栈中的唯一的一个数就是运行结果了。
函数OP.实现如下。 参数 ch 是操作符
void Caculator::OP(const char &ch) { long RightOperand = opd.top(); opd.pop(); long LeftOperand = opd.top(); // 这两个操作数的顺序不能错 opd.pop(); switch(ch) { case '+': LeftOperand += RightOperand; break; case '-': LeftOperand -= RightOperand; break; case '*': LeftOperand *= RightOperand; break; case '/': if (RightOperand == 0) // 除数为 0 { cout<<"大哥啊,除数为0了!"<<endl; system("pause"); exit(1); } else LeftOperand /= RightOperand; default: cout<<"非法操作符!!----:"<<ch<<endl; system("pause"); exit(1); } opd.push(LeftOperand); // 把求得的值压入堆栈 } |
opd 是操作数栈,是一个类成员变量 .定义是 stack<long> opd; // 只能进行整数的运算
简单吧……
关键是把表达式转换成后缀的……
这个实现中未对表达式是否合法进行判断,所以非法的表达式会造成程序崩溃……表达式的检查也可以在扫描的过程中完成的。