发布一个基于Spirit的表达式解析库
2009-08-18 21:00
162 查看
整个库只有一个Expr2.h文件,它主要基于Boost中的Spirit库和Function库实现。适用于VC(7.1以上),C++Builder和GCC。
IOpPtr op = equ.CreateOperator("1+2*3/(4+5)^6");
double result = op->Op(NULL);
CEquation支持加减乘除和幂操作
const char* lastp;
IOpPtr op = equ.CreateOperator(exp, &lastp); // lastp指出最后解析的位置
if(!op)
{
cout << std::string(exp,lastp) << "<这里有错误>" << lastp << endl;
}
// 加入常量
equ.AddConst("e",2.1718);
equ.AddConst("pi",3.1415926);
IOpPtr op = equ.CreateOperator("1+e*3/(pi+5)");
double result = op->Op(NULL);
CEquation equ;
// 加入函数
equ.AddUnaryFunc("sin", (double (*)(double))sin);
equ.AddUnaryFunc("dao", bind1st( divides<double>(), 1.0 ) ); //倒数
IOpPtr op = equ.CreateOperator("1+dao(e*3)/sin(pi+5)");
double result = op->Op(NULL);
AddUnaryFunc方法接收一个字符串和一个要求形式为double func(double)的函数或仿函数。字符串作为表达式中的函数名。另外,还有一个AddBinaryFunc方法,用于加入两个参数的函数(如atan2)。
CEquation equ;
IOpPtr op = equ.CreateOperator("1+sin(pi/X)^Y");
cout << "变量名:";
const CVariableList &vl = op->GetVariables();
for(CVariableList::const_iterator itr=vl.begin(); itr!=vl.end(); ++itr)
{
cout << itr->Name << " , ";
}
cout << endl << "X=10, Y=5 时,方程的解:";
double v[]={10,5}; //按变量出现的顺序写变量对应的数值
cout << op->Op(v) << endl;
IOpPtr的GetVariables方法返回表达式中所有的变量(CVariableList 其实是一个vector<TVariable>),TVariable结构中只有一个Name成员。
CEquation equ;
equ.AddEquation("G = 9.8");
IOpPtr op = equ.CreateOperator("1+G*3");
double result = op->Op(NULL);
AddEquation方法接受的字符串表达式必须为"名称=公式"的形式。
CEquation equ;
...
equ.AddEquation("f = 1+sin(pi/X)^Y"); //定义f
IOpPtr op = equ.CreateOperator("f*(20/Y)"); //f作为1+sin(pi/X)^Y被代入
...
CEquation equ;
equ.AddConst("e",2.1718);
equ.AddUnaryFunc("lg", p_unary_f(std::log10));
equ.AddEquation("log(base, exp) = lg(exp)/lg(base)");
equ.AddEquation("ln(x) = log(e,x)"); //新生成一个ln函数
IOpPtr op = equ.CreateOperator("ln(3)"); //使用ln函数
注:p_unary_f在Expr2中被定义为double (*p_unary_f)(double)
这个库是大小写敏感的,不过很简易通过改写TVariable的两个比较操作实现大小写不敏感。
BUG在所难免,如果大家有改进或修复一定要回复哦(基于GPL发布)!希望这个库能对大家有用
下载地址:http://www.cpp-prog.com/2009/0818/147.html
最简用法:
CEquation equ;IOpPtr op = equ.CreateOperator("1+2*3/(4+5)^6");
double result = op->Op(NULL);
CEquation支持加减乘除和幂操作
定位解析错误位置:
const char* exp = "1+2*3/((4+5)"; //错误的表达式const char* lastp;
IOpPtr op = equ.CreateOperator(exp, &lastp); // lastp指出最后解析的位置
if(!op)
{
cout << std::string(exp,lastp) << "<这里有错误>" << lastp << endl;
}
在表达式中使用常量
CEquation equ;// 加入常量
equ.AddConst("e",2.1718);
equ.AddConst("pi",3.1415926);
IOpPtr op = equ.CreateOperator("1+e*3/(pi+5)");
double result = op->Op(NULL);
为CEquation类加入函数支持
光有加减乘除是不够的,CEquation还支持实时加入函数支持。CEquation equ;
// 加入函数
equ.AddUnaryFunc("sin", (double (*)(double))sin);
equ.AddUnaryFunc("dao", bind1st( divides<double>(), 1.0 ) ); //倒数
IOpPtr op = equ.CreateOperator("1+dao(e*3)/sin(pi+5)");
double result = op->Op(NULL);
AddUnaryFunc方法接收一个字符串和一个要求形式为double func(double)的函数或仿函数。字符串作为表达式中的函数名。另外,还有一个AddBinaryFunc方法,用于加入两个参数的函数(如atan2)。
支持表达式中的变量
当表达式中有字母并且不属于常量时,CEquation类将其它作为变量处理CEquation equ;
IOpPtr op = equ.CreateOperator("1+sin(pi/X)^Y");
cout << "变量名:";
const CVariableList &vl = op->GetVariables();
for(CVariableList::const_iterator itr=vl.begin(); itr!=vl.end(); ++itr)
{
cout << itr->Name << " , ";
}
cout << endl << "X=10, Y=5 时,方程的解:";
double v[]={10,5}; //按变量出现的顺序写变量对应的数值
cout << op->Op(v) << endl;
IOpPtr的GetVariables方法返回表达式中所有的变量(CVariableList 其实是一个vector<TVariable>),TVariable结构中只有一个Name成员。
使用字符串表达式加入常量
除了使用AddConst方法外,CEquation也能识别字符串表达式中的常量定义:CEquation equ;
equ.AddEquation("G = 9.8");
IOpPtr op = equ.CreateOperator("1+G*3");
double result = op->Op(NULL);
AddEquation方法接受的字符串表达式必须为"名称=公式"的形式。
多级定义
AddEquation不仅可以自动识别常量,也可以把整个公式赋值给一个变量。当字符串中"="右边的公式含有变量时,就相当于定义一个子公式,如:CEquation equ;
...
equ.AddEquation("f = 1+sin(pi/X)^Y"); //定义f
IOpPtr op = equ.CreateOperator("f*(20/Y)"); //f作为1+sin(pi/X)^Y被代入
...
函数定义(C++Builder 2006以下版本不适用)
还是AddEquation方法,如果等号左边的形式是:函数名(变量,变量,...)的形式。那么将生成一个新的函数:CEquation equ;
equ.AddConst("e",2.1718);
equ.AddUnaryFunc("lg", p_unary_f(std::log10));
equ.AddEquation("log(base, exp) = lg(exp)/lg(base)");
equ.AddEquation("ln(x) = log(e,x)"); //新生成一个ln函数
IOpPtr op = equ.CreateOperator("ln(3)"); //使用ln函数
注:p_unary_f在Expr2中被定义为double (*p_unary_f)(double)
这个库是大小写敏感的,不过很简易通过改写TVariable的两个比较操作实现大小写不敏感。
BUG在所难免,如果大家有改进或修复一定要回复哦(基于GPL发布)!希望这个库能对大家有用
下载地址:http://www.cpp-prog.com/2009/0818/147.html
相关文章推荐
- 一个基于JRTPLIB的轻量级RTSP客户端(myRTSPClient)——收流篇:(四)example代码解析
- 小八——WebGL心路历程(2),一个基于Three.js的webGL程序解析
- WCF技术剖析之二十七: 如何将一个服务发布成WSDL[基于WS-MEX的实现](提供模拟程序)
- 发布一个基于 Reactor 模式的 C++ 网络库
- href 一个正则表达式的解析 ? 号解析
- 发布一个原创的基于Ajax的通用(组合)查询
- 分享一个分布式消息总线,基于.NET Socket Tcp的发布-订阅框架,附代码下载 推荐
- 基于注解的spring+dubbo发布一个简单的helloWord服务及调用
- (基于Java)编写编译器和解释器-第5章:解析表达式和赋值语句-第二部分(连载)
- 发布一个基于jQuery的可编辑表格插件–ayGrid
- 发布一个基于TokyoTyrant的C#客户端开源项目
- WCF技术剖析之二十七: 如何将一个服务发布成WSDL[基于HTTP-GET的实现](提供模拟程序)
- 发布一个原创的基于Ajax的通用(组合)查询
- 发布一个基于CSDN Code的学习测试仓库
- 发布一个基于jquery的无限层级下拉控件
- 一个技术汪的开源梦 —— 基于 .Net Core 的组件 Nuget 包制作 & 发布
- 一个基于反射的消息发布订阅模型详解
- 发布一个基于Go语言的 SSH 远程终端 WebConsole
- 利用Boost解析正则表达式,解析一个范围示例
- boost spirit 关于复杂表达式的解析