如何实现:
(a+b)*c*(d+e)
用程序分解为
a*c*d+a*c*e+b*c*d+b*c*e
其中a,..,e是字符串
(a+b)*c*(d+e)
用程序分解为
a*c*d+a*c*e+b*c*d+b*c*e
其中a,..,e是字符串
解决方案 »
- 关于数组的一个问题
- 检索对话框的设计??
- 为什么在XP下连接SQL Server数据库可以,但在98下就显示“拒绝访问”?
- 请问安装程序制作用什么样的好一点?
- Memo字段(Access)的字符串搜索问题?
- 关于adoquery1.append;........adoquery1.post;的问题-------------在线等待!!
- 怎样调用动态连接库中的函数?急!在线等候!
- 怎样实现checkedlistbox换列?
- 如何知道当前页打印完成了?
- form2在form1显示的问题
- CS结构,多人同时录入数据,怎么样才能使用生成的货号不重复呢(不要用自动ID,因为货号需要加入一些前置字母)
- 请教高手!
呵呵呵呵~~
定义F,G
F:=a+b
g:=d+e
其中:a,b,..,c 等是不定的字符串,
但是不会包括"+","*","(",")"
运算符为"+","*",优先级"*">"+"我没学过delphi,
准备用堆栈实现
正在写写好后会把代码贴出来的!!!
只是希望那位有更好的实现,贴出来共享
f := a+b;
g := d+e;
f*c*g;
再把三个相乘,不就可以了,何必非得要一步
((a+b)*c+d)*e+f
呢--------------------------我想到的方法是,用递归(分析语法)加动态的多维结构(存储多项式)实现。可是对delphi不熟,希望各位帮忙。
说就容易,做是挺难的。估计至少用两天工作日。(1天写程序,1天测试和修复bug)
随便写了个,请多指教。
function GetResult(source :string) :string; //主函数
var
iPos :integer;
a,b :string;
function AddSign(b :string) :string;
var
iPos :integer;
begin
iPos := pos('(',b);
if iPos = 0 then
begin
b := '(' + b;
end;
iPos := pos(')',b);
if iPos = 0 then
begin
b := b + ')';
end;
result := b;
end;
function PutoffSign(b :string) :string; //去掉符号 "("和")";
var
iPos :integer;
begin
iPos := pos('(',b);
if iPos <> 0 then
begin
delete(b,iPos,1);
end;
iPos := pos(')',b);
if iPos <> 0 then
begin
delete(b,iPos,1);
end;
result := b;
end;
function GetSecondSignPos(b :string) :integer; //获得第二个符号"("
var
iPos :integer;
PosA :integer;
begin
result := -1;
delete(b,1,1);
iPos := pos('(',b);
if iPos= 0 then exit;
result := iPos +1;
end;
function GetMulty(source :string) :string; //基本运算单元 模型 y := (a + b)*( c + d)
var
i ,j :integer;
a,b :TstringList;
iPos :integer;
function GetCell(temp :string) :TstringList;
var
iPos :integer;
begin
Result := Tstringlist.Create;
iPos := pos('(',temp);
if iPos <>0 then
begin
delete(temp,iPos,1);
end;
iPos := pos(')',temp);
if iPos <> 0 then
begin
delete(temp,iPos,1);
end;
while(true)do
begin
iPos := pos('+',temp);
if iPos = 0 then
begin
Result.Add(temp);
break;
end else
begin
Result.Add(copy(Temp,1,iPos-1));
Delete(temp,1,iPos);
end;
end;
end;
begin
iPos := GetSecondSignPos(source);
if iPos = -1 then
begin
result := source;
exit;
end;
a := GetCell(copy(source,1,iPos-2));
delete(source,1,iPos-1);
b := GetCell(source);
for i := 0 to a.Count -1 do
begin
for j := 0 to b.Count -1 do
begin
if result = '' then
begin
result := a.Strings[i]+'*'+b.Strings[j];
end else
begin
result := result +' + '+ a.Strings[i]+'*'+b.Strings[j] ;
end;
end;
end;
a.Free;
b.Free;
end;begin
//先解析
a := '';
while(true)do
begin
iPos := pos('*',source);
if iPos = 0 then
begin
a := a + Addsign(source);
break;
end else
begin
b := copy(source,1,iPos-1);
a := a + Addsign(b) + '*';
Delete(source,1,iPos);
end;
end;
source := a; while(true)do
begin
iPos := GetSecondSignPos(source);
if iPos = -1 then
begin
source := PutoffSign(source);
break;
end else
begin
a := Copy(source,1,iPos-1);
delete(source,1,iPos-1);
iPos := GetSecondSignPos(source);
if iPos = -1 then
begin
source := GetMulty(a+source);
end else
begin
b := copy(source,1,iPos-2);
delete(source,1,iPos-1);
source := AddSign(GetMulty(a+b))+'*'+source;
end;
end;
end;
result := source;
end;procedure TForm1.Button1Click(Sender: TObject); //调用方法
begin
Edit2.Text := GetResult(Edit1.Text);
end;
你的算法可以实现,我一定加分给你想问一下,还有别的实现吗?
栈的,或是树的遍历我会另开贴给分的
------ ccc0808xx(加加)
你的算法还有点问题
如
a*(b+c)*d+e
算法是基于你最初给的格式,其他的格式的解析没有打算去写,实现思路也一样,(一)
格式标准化(二)找出关键字(三)将格式按照栈解吸。曾经用汇编写了个,所以栈比较好考虑。
我猜你多半是想用它作一个解析器吧!不过我建议你使用现在有的成熟的控件。我用的脚本
解析器都是用的人家的控件,两个字:方便。如果需要,发邮箱到我QQ47128653,免费送!
你的第二个问题,非标准格式的解析,等我有空了 用栈帮你写个!
不懂 Delphi, 我用java写过简单的表达式的解析,希望对楼主有所帮助
http://dev.csdn.net/develop/article/20/20719.shtm
看其中 “面向对象的java实现”里面的类设计。使用二叉树,因为+-*/都是二元运算,a*b*c 其实是(a*b)*c 的简写,a-b+c其实是(a-b)+c的简写,绝不会等于a-(b+c)从字符串解析成二叉树要用栈,编译原理里面有详细的介绍。二叉树每个节点是一个 Expression ,每个 Expression 包含左子节点,运算符,右子节点。遍历二叉树的时候,对每一个节点 Expression,依次比较
1、 本节点运算符和左子节点运算符的优先级
2、 本节点运算符和右子节点运算符的优先级
如果本节点运算符优先级高于子节点(*/优先级大于+-),就调整。注意纯数(对应上面java设计中的Nmbuer类)的运算符优先级最高。举例如下:
表达式:(a-b)*(c+d)
解析为
*
- +
a b c d
遍历到*代表的那个节点时,比较如下:
1、 *和-比较,需要调整。所以调整为:
-
* *
a + b +
上面+这个节点复制了一份,变成了两个。这个节点复制是深拷贝,其子节点都需要复制。调整之后,本节点要重新进行1、2两步比较。最后直接使用根节点的 toString() (这也是一个递归方法) 就能显示出所要的结果。
说得很清楚了
那位高人帮忙实现一下,练练手。---------------------------------------
而我的方法是用一个递归直接解析成
{
{A,B,C}
{D,E}
{F,G,H }
}
这也是我要的最终形式
那么
1,解线性方程因式分解
比如:
输入:"a^2 - 2*a*b + b^2"
输出:"(a-b)*(a-b)"提示:好好回家看看线性代数的书哦。 2,级数:输入:e ^ x
输出:∑ x ^ n / n!哈哈,第一题可能答出,第二题你要苦练10年哦!!!
原理上面已经有人说了,估计也没什么别的方法
2.用树
上面也有人说了.
3.用字符替换
这个用的资源比较少,用循环检查表达式的')'找到后就找他左边的最近的'(',然后计算里面的结果,将得到的结果替换掉括号之间的内容,如此循环.无论哪种方法,递归都是必须的.原理大同小异.第三种方法实现代码
http://borland.mblogger.cn/lw549/posts/808.aspx
{
{A,B,C}
{D,E}
{F,G,H }
}------
type
TRuleList=class(TStringList)
private
//确定需要添加项的列数,例:(a+b)*c 中添加 c 时为2 。
addcount:integer;
public
Constructor Create();
procedure addColumn(); //加列
procedure addItem(const item:string); //为account列加新行
procedure addList(const childlist:TRuleList); //加新表
function getRule():string;
Destructor Destroy();override;
end;-----------
//主函数
function getResult(const source:string):string;
var
ipos:integer; //原始字符串遍历下标
bracketcount:integer; //括号记数
wordflag:0..2; //0-未开始读词;1-已开始读词;2-括号结束
aword:string; //词
//err:string; //出错信息
rulelist:TRuleList; //规则 function getRule(const source:string):TRuleList; //解析函数
var
rlist,childlist:TRuleList;
begin
result:=nil;
rlist:=TRuleList.Create();
try
while ipos<=length(source) do
begin
case source[ipos] of
AnsiChar('*'):
begin
if wordflag=0 then
begin
raise Exception.Create('语法错误: 第'+inttostr(ipos)+'字节 * 号附近');
end;
if wordflag=1 then
begin
rlist.addItem(aword);
end;
wordflag:=0;
aword:='';
ipos:=ipos+1;
end; //'*'
AnsiChar('+'):
begin
if wordflag=0 then
begin
raise Exception.Create('语法错误: 第'+inttostr(ipos)+'字节 + 号附近');
end;
if wordflag=1 then
rlist.addItem(aword);
rlist.addColumn();
wordflag:=0;
aword:='';
ipos:=ipos+1;
end; // '+'
AnsiChar('('):
begin
bracketcount:=bracketcount+1;
ipos:=ipos+1;
if wordflag=1 then
begin
rlist.addItem(aword);
wordflag:=0;
aword:='';
end;
childlist:=getRule(source);//递归
if childlist<>nil then
begin
rlist.addlist(childlist);
childlist.Free();
end
else
begin
break;
end
end; // '('
AnsiChar(')'):
begin
bracketcount:=bracketcount-1;
ipos:=ipos+1;
if(bracketcount<0) then
begin
raise Exception.Create('语法错误: 第'+inttostr(ipos-1)+'字节 ) 号附近,括号不匹配');
end;
if wordflag=1 then
begin
rlist.addItem(aword);
wordflag:=2;
aword:='';
end;
if wordflag=0 then
begin
raise Exception.Create('语法错误: 第'+inttostr(ipos-1)+'字节 ) 号附近');
end;
if rlist.Count=0 then
begin
raise Exception.Create('语法错误: 第'+inttostr(ipos-1)+'字节 ) 号附近,空括号');
end;
result:=rlist;
break;
end; // ')'
else
begin
aword:=aword+source[ipos];
wordflag:=1;
ipos:=ipos+1;
end; //else
end; //case
end; //while
//showMessage(inttostr(bracketcount)+' '+rlist.getRule()); //调试信息
if (bracketcount<>0) and (ipos>=length(source)) then
begin
raise Exception.Create('语法错误:结束时括号不匹配');
end; if (bracketcount=0) and (ipos>length(source)) then //遍历完成,正常返回
begin
if wordflag=1 then
begin
rlist.addItem(aword);
wordflag:=0;
end;
result:=rlist;
end;
//else 未完成(出错,或是递归返回) except
on Exception do
begin
if rlist<>nil then
begin
rlist.Free();
end;
raise; //重发
end;
end;//except
end; //function getRulebegin
ipos:=1;
rulelist:=nil;
wordflag:=0;
aword:='';
bracketcount:=0;
try
rulelist:=getRule(source); //获得规则
if rulelist<>nil then
begin
result:=rulelist.getRule();
rulelist.Free();
end
except
on e:Exception do
showMessage(e.Message);
end;
end; //function getResult
procedure TForm1.Button1Click(Sender: TObject);
begin
Edit2.Text:=getResult(Edit1.Text);
end;
if str =‘(a+b)*c*(d+e)’then
str:='a*c*d+a*c*e+b*c*d+b*c*e'
;哈哈,搞笑一下