c++ 实现数学表达式解析

来源:互联网 发布:电话薄软件 编辑:程序博客网 时间:2024/06/06 17:32

在最近的项目中希望使用一个简单的表达式计算功能, 网上有开源的库,但是体积庞大,编译链接缓慢。


所以最后还是自己实现了一个。  支持几乎所有的数学运算符, 以及<cmath> 内置的函数。


实现原理简述:


c++实现表达式计算的思路一般有两种, (此处使用的是后者。)


1.   使用面向对象的多态特性, 对每一种运算符实现一个表达式类,  类似
class Exp;
class AddExp:Exp; 
class MulExp:Exp; 
....
虚拟重载evaluate()求值函数, 在解析表达式的过程中构建一颗表达式树,同时根据运算符优先级对树做旋转。




2. 基于堆栈
使用两个栈 O 和 N, 一个存算符, 一个存操作数, 根据算符优先级出入栈。


线性扫描表达式, 比较当前算符 和栈顶算符的优先级(还要考虑结合性),如果后者优先级高, 则从数值栈顶取出元素并计算,然后把返回值入栈。 
否则 操作符/操作数依次入栈


实例: 计算 1*2+3 具体过程
依次入栈
push 1; push *; push 2     
此时栈内元素如下, 下一个算符为'+'
N |1|2| 
O |*|
由于栈顶端算符为*, 优先级高于+, 所以先计算*, 从数值栈顶取出两个操作数1和2, 相乘得返回值2,入栈
pop 1; pop 2; pop *; push 1*2
N |2| 
O |
然后再处理后面的‘+’
N |2|3| 
O |+|
-->
N |5| 
O |


大致思路如上述

3. 实现  


1. 实现一个函数 tokenize  把表达式拆解为一个一个独立的token  忽略空格等

此处的token指 数值/算符/变量

2. 实现一个函数evaluate 根据上述原理扫描已经过预处理的token序列, 实现计算。

3.对左值的处理也考虑了, 具体见源码。


代码见资源。

http://download.csdn.net/detail/tiankong_bear/9668171



更正:

上面的代码里面有一个bug

line 400 开始应该改为

                if (RPAR == it->opr) {
                    if (prevOp != LPAR) {throw ExprError("parenthese unmatch");}
                    sOpr.pop();
                } else {
                    sOpr.push(it->opr);
                }

否则会有括号匹配问题。


资源代码 已更正。

1 0