| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1157 人关注过本帖
标题:如何实现混合运算(89-3*2+(54-42)/3)?
只看楼主 加入收藏
超超小火星
Rank: 1
等 级:新手上路
帖 子:48
专家分:0
注 册:2008-10-31
结帖率:100%
收藏
 问题点数:0 回复次数:2 
如何实现混合运算(89-3*2+(54-42)/3)?
不同于简单的计算器程序,窗体上只有两个edit  一个用于输入 一个用于输出结果 和一个button,要求点击按钮就自动运算输入框中的混合运算。请教大侠们怎么实现呀?
 

[ 本帖最后由 超超小火星 于 2009-11-10 12:57 编辑 ]
搜索更多相关主题的帖子: 运算 
2009-11-10 12:55
shuang200911
Rank: 5Rank: 5
等 级:职业侠客
威 望:2
帖 子:39
专家分:337
注 册:2009-11-2
收藏
得分:0 
{*************************************************************************
1、只支持乘除加减、小括号,如:9/3+(89-3*2+(54-42)/3)。
2、也许会存在一些BUG,请各位大虾修正
**************************************************************************}
unit Main;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, StrUtils;

type
  TDirection = (dcForward, dcBack);

  TForm1 = class(TForm)
    edtExpression: TEdit;
    edtResult: TEdit;
    btnCalculate: TButton;
    procedure btnCalculateClick(Sender: TObject);
  private
    function GetExpression(var StartPos, EndPos: Integer; AExpression: string): string;
    function Calculate(AExpression: string): string;
    function CalculateEx(FirstNum, SecondNum, ASign: string): string;
    function GetLastSignPos(ASign, AExpression: string): Integer;
    function GetLatestSignPos(StartPos: Integer; AExpression: string): Integer;
    function GetNumber(var ResultPos: Integer;AExpression: string;
                      Position: Integer; Direction: TDirection): string;
    function CalculateAll(AExpression: string): string;
    procedure CorrectExpression(var AExpression: string);
    function IsANegative(AExpression: string): Boolean;
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.btnCalculateClick(Sender: TObject);
begin
  edtResult.Text :=  CalculateAll(edtExpression.Text);
end;

function TForm1.Calculate(AExpression: string): string;
var
  Pos1: Integer;  {符号*位置}
  Pos2: Integer;  {符号/位置}
  Pos3: Integer;  {符号+位置}
  Pos4: Integer;  {符号-位置}

  FirstNum, SecondNum, ResultNum: string;    //第一个数值,第二个数值,计算结果值

  StartPos, EndPos: Integer;    //二元表达式的开始位置、结束位置
  FNegative: Boolean;    //负数
begin
  Result := '';
  StartPos := -1;
  EndPos := -1;
  FNegative := False;

  CorrectExpression(AExpression);   //表达式修正

  while Length(AExpression) > 0 do
  begin
    CorrectExpression(AExpression);   //表达式修正

    Pos1 := Pos('*', AExpression);
    Pos2 := Pos('/', AExpression);
    Pos3 := Pos('+', AExpression);
    Pos4 := Pos('-', AExpression);

    if IsANegative(AExpression) then   //为一个负数的时
    begin
      Result := AExpression;
      Exit;
    end;

    if (Pos1 > 0) or (Pos2 > 0) then   //有乘除先算乘除
    begin
      if Pos1 > Pos2 then    //乘号的位置在除号的后面, 按照从左至右的顺序, 先算除法
      begin
        if Pos2 > 0 then   //如果有除法
        begin
          FirstNum := GetNumber(StartPos, AExpression, Pos2, dcBack);
          SecondNum := GetNumber(EndPos, AExpression, Pos2, dcForward);
          ResultNum := CalculateEx(FirstNum, SecondNum, '/');
        end
        else    //没有除法就算乘法
        begin
          FirstNum := GetNumber(StartPos, AExpression, Pos1, dcBack);
          SecondNum := GetNumber(EndPos, AExpression, Pos1, dcForward);
          ResultNum := CalculateEx(FirstNum, SecondNum, '*');
        end;
      end
      else    //乘号的位置在除号的前面, 按照从左至右的顺序, 先算乘法
      begin
        if Pos1 > 0 then    //如果有乘法
        begin
          FirstNum := GetNumber(StartPos, AExpression, Pos1, dcBack);
          SecondNum := GetNumber(EndPos, AExpression, Pos1, dcForward);
          ResultNum := CalculateEx(FirstNum, SecondNum, '*');
        end
        else   //没有乘法就算除法
        begin
          FirstNum := GetNumber(StartPos, AExpression, Pos2, dcBack);
          SecondNum := GetNumber(EndPos, AExpression, Pos2, dcForward);
          ResultNum := CalculateEx(FirstNum, SecondNum, '/');
        end;
      end;
    end
    else if (Pos3 > 0) or (Pos4 >0) then   //没有乘除算加减
    begin
      if Pos3 > Pos4 then     //加号的位置在减号位置的后面, 按照从左至右的顺序, 先算减法
      begin
        if Pos4 > 1 then     //如果有减法
        begin
          FirstNum := GetNumber(StartPos, AExpression, Pos4, dcBack);
          SecondNum := GetNumber(EndPos, AExpression, Pos4, dcForward);
          ResultNum := CalculateEx(FirstNum, SecondNum, '-');
        end
        else    //没有减法就算加法
        begin
          FirstNum := GetNumber(StartPos, AExpression, Pos3, dcBack);
          SecondNum := GetNumber(EndPos, AExpression, Pos3, dcForward);
          ResultNum := CalculateEx(FirstNum, SecondNum, '+');
        end;
      end
      else    //加号的位置在减号位置的前面, 按照从左至右的顺序, 先算加法
      begin
        if Pos3 > 0 then    //如果有加法
        begin
          FirstNum := GetNumber(StartPos, AExpression, Pos3, dcBack);
          SecondNum := GetNumber(EndPos, AExpression, Pos3, dcForward);
          ResultNum := CalculateEx(FirstNum, SecondNum, '+');
        end
        else   //没有加法算减法
        begin
          if Pos4 = 1 then    //减号在最前面,如-7-19
          begin
            AExpression := Copy(AExpression, 2, MaxInt);
            FNegative := True;
            Continue;
          end;
          if FNegative then
          begin
            AExpression := Format('-%s', [AExpression]);
            Inc(Pos4);
            FNegative := False;
          end;  
          FirstNum := GetNumber(StartPos, AExpression, Pos4, dcBack);
          SecondNum := GetNumber(EndPos, AExpression, Pos4, dcForward);
          ResultNum := CalculateEx(FirstNum, SecondNum, '-');
        end;
      end;
    end
    else    //没有乘除加减法即退出
      Break;

    AExpression := Format('%s%s%s', [Copy(AExpression, 1, StartPos - 1),
                          ResultNum, Copy(AExpression, EndPos + 1, MaxInt)]);
  end;
  Result := AExpression;
end;

function TForm1.CalculateAll(AExpression: string): string;
var
  StartPos, EndPos: Integer;  //子表达式的开始位置/结束位置
  SubExpression: string;  //子表达式
  ResultValue: string;   //计算结果
begin
  while Length(AExpression) > 0 do
  begin
    SubExpression := GetExpression(StartPos, EndPos, AExpression);
    ResultValue := Calculate(SubExpression);
    AExpression := Format('%s%s%s', [Copy(AExpression, 1, StartPos - 1), ResultValue,
                         Copy(AExpression, EndPos + 1, MaxInt)]);
    if (Pos('*', AExpression) = 0) and
       (Pos('/', AExpression) = 0) and
       (Pos('+', AExpression) = 0) and
       (Pos('-', AExpression) = 0) then Break;     //一个正数时

    if (Pos('*', AExpression) = 0) and
       (Pos('/', AExpression) = 0) and
       (Pos('+', AExpression) = 0) and
       (Pos('-', AExpression) = 1) then Break;     //一个负数时
  end;
  Result := AExpression;
end;

function TForm1.CalculateEx(FirstNum, SecondNum, ASign: string): string;
var
  fFirstNum, fSecondNum: Double;
begin
  Result := '';
  fFirstNum := StrToFloat(FirstNum);
  fSecondNum := StrToFloat(SecondNum);
  if ASign = '+' then
    Result := FloatToStr(fFirstNum + fSecondNum);
  if ASign = '-' then
    Result := FloatToStr(fFirstNum - fSecondNum);
  if ASign = '*' then
    Result := FloatToStr(fFirstNum * fSecondNum);
  if ASign = '/' then
    Result := FloatToStr(fFirstNum / fSecondNum);
end;

{取括号内表达式}
function TForm1.GetExpression(var StartPos, EndPos: Integer; AExpression: string): string;
begin
  if Pos('(', AExpression) > 0 then
  begin
    StartPos := GetLastSignPos('(', AExpression);
    EndPos := GetLatestSignPos(StartPos, AExpression);
    Result := Copy(AExpression, StartPos + 1, EndPos - StartPos - 1);
  end
  else
  begin
    StartPos := 1;
    EndPos := Length(AExpression);
    Result := AExpression;
  end;
end;


function TForm1.GetLatestSignPos(StartPos: Integer;
  AExpression: string): Integer;
var
  iCount: Integer;
  sLenght: Integer;  //字符串长度
  AExpr: string[250];
begin
  Result := -1;
  AExpr := AExpression;
  sLenght := Ord(AExpr[0]);
  for iCount := StartPos to sLenght do
  begin
    if AExpr[iCount] = ')' then
    begin
      Result := iCount;
      Break;
    end;         
  end;
end;

{取特定字符在表达式里的最后出现的位置}
function TForm1.GetLastSignPos(ASign, AExpression: string): Integer;
var
  iCount: Integer;
  sLenght: Integer;  //字符串长度
  AExpr: string[250];
begin
  Result := -1;
  AExpr := AExpression;
  sLenght := Ord(AExpr[0]);
  for iCount := 1 to sLenght do
  begin
    if AExpr[iCount] = ASign then
      Result := iCount;
  end;
end;

{在一个字符串里,根据指定的位置,向前/后取一个数字}
function TForm1.GetNumber(var ResultPos: Integer; AExpression: string;
  Position: Integer; Direction: TDirection): string;
var
  AExpr: string[250];
  iCount: Integer;
  AValue: string;
  SpecialPos: Integer;   //特殊位置
begin
  AExpr := AExpression;
  iCount := Position;
  AValue := '';
  case Direction of
    dcBack:
    begin
      Dec(iCount);
      while (iCount > 0) do
      begin
        if (iCount = 1) and (AExpr[iCount] = '-') then
        begin
          AValue := Format('%s%s', [AExpr[iCount], AValue]);
          ResultPos := iCount;
          Break;
        end;
        if (AExpr[iCount] = '+') or
           (AExpr[iCount] = '-') or
           (AExpr[iCount] = '*') or
           (AExpr[iCount] = '/') then  Break;
        AValue := Format('%s%s', [AExpr[iCount], AValue]);
        ResultPos := iCount;
        Dec(iCount);
      end;
    end;
    dcForward:
    begin
      Inc(iCount);
      SpecialPos := iCount;   
      while iCount <= Ord(AExpr[0]) do
      begin
        if (iCount = SpecialPos) and (AExpr[iCount] = '-') then   //乘(除)后面跟一个负数时
        begin
          AValue := Format('%s%s', [AValue, AExpr[iCount]]);
          ResultPos := iCount;
          Inc(iCount);
          Continue;
        end;
        if (AExpr[iCount] = '+') or
           (AExpr[iCount] = '-') or
           (AExpr[iCount] = '*') or
           (AExpr[iCount] = '/') then  Break;
        AValue := Format('%s%s', [AValue, AExpr[iCount]]);
        ResultPos := iCount;
        Inc(iCount);
      end;  
    end;  
  end;
  Result := AValue;
end;

{表达式修正}
procedure TForm1.CorrectExpression(var AExpression: string);
begin
  AExpression := StringReplace(AExpression, '--', '+', []);   //负负得正
  AExpression := StringReplace(AExpression, '+-', '-', []);   //加上一个负数等于减去该数绝对值
end;

{判断一个表达式是否为一个负数}
function TForm1.IsANegative(AExpression: string): Boolean;
var
  OutVal: Double;
begin
  Result := TryStrToFloat(AExpression, OutVal);
  Result := OutVal < 0;
end;

end.
2009-11-15 19:32
studyrjt
Rank: 1
等 级:新手上路
帖 子:1
专家分:0
注 册:2010-3-2
收藏
得分:0 
如何实现混合运算(89-3*2+(54-42)/3)?
unit TestUnit;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, jpeg, ExtCtrls;

type
  TDLLForm = class(TForm)
    Button1: TButton;
    Edit1: TEdit;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  DLLForm: TDLLForm;

implementation

{$R *.dfm}

procedure SepNum(SourceS:string;var destS:array of string);
var
  s1,s2:string;
  i,j:integer;
begin
  s1:=sourceS;
  j:=1;
  for i := 1 to length(s1) do
   begin
   if s1[i] in ['+','-','*','/','(',')'] then
    begin
     dests[j]:=s1[i];
     inc(j);
    end;
   if s1[i] in ['0'..'9'] then
     begin
      dests[j]:=dests[j]+s1[i];
      if i<length(s1) then
        if s1[i+1] in ['+','-','*','/','(',')']  then
       inc(j);
     end;
   end;
end;

procedure Ps(var S:array of string);
var
 i,j:integer;
 temp:array of string;
begin
j:=1;
setlength(temp,high(s));
  for I := 1 to high(s) do
    if s[i]<>'' then
     begin
     temp[j]:=s[i];
     inc(j);
     end;
  for i := 1 to high(temp)  do
    s[i]:=temp[i];
end;

// 做* / 运算;
procedure sf1(var s1:array of string);
var
 i,j:integer;
begin

 for I := 2 to high(s1)-1  do
   begin
   if s1[i]='*' then
     if (s1[i-1]<>'(') and (s1[i-1]<>')') and (S1[i+1]<>')') and (S1[i+1]<>'(')  then
       begin
       s1[i+1]:=floattostr(strtofloat(s1[i-1])*strtofloat(s1[i+1]));
       s1[i-1]:='';
       s1[i]:='';
       end;

   if s1[i]='/' then
     if (s1[i-1]<>'(') and (s1[i-1]<>')') and (S1[i+1]<>')') and (S1[i+1]<>'(')  then
       begin
       s1[i+1]:=floattostr(strtofloat(s1[i-1])/strtofloat(s1[i+1]));
       s1[i-1]:='';
       s1[i]:='';
       end;
   end;
end;

// 做+ /
procedure sf2(var s1:array of string);
var
 i:integer;
begin
 for i := 2 to high(s1)-1 do
 begin
  if s1[i]='+' then
   if (s1[i-1]<>'(') and (s1[i-1]<>')') and (S1[i+1]<>')') and (S1[i+1]<>'(') and (s1[i-2]<>'*') and (s1[i-2]<>'/') and (s1[i+2]
<>'*') and (s1[i+2]<>'/') then
    begin
     s1[i+1]:=floattostr(strtofloat(s1[i-1])+strtofloat(s1[i+1]));
     s1[i-1]:='';
     s1[i]:='';
    end;
  if s1[i]='-' then
   if (s1[i-1]<>'(') and (s1[i-1]<>')') and (S1[i+1]<>')') and (S1[i+1]<>'(')and (s1[i-2]<>'*') and (s1[i-2]<>'/') and (s1[i+2]
<>'*') and (s1[i+2]<>'/')  then
    begin
     s1[i+1]:=floattostr(strtofloat(s1[i-1])-strtofloat(s1[i+1]));
     s1[i-1]:='';
     s1[i]:='';
    end;
 end;
end;

// 去括号
procedure sf3(var s1:array of string);
var
 i:integer;
begin
 for i := 1 to high(s1)-2 do
  if (s1[i]='(') and (s1[i+2]=')') then
     begin
     s1[i]:='';
     s1[i+2]:='';
     end;
end;

procedure TDLLForm.Button1Click(Sender: TObject);
var
  s1:string;
  s2:array of string;
  i:integer;
begin
   s1:=edit1.Text;
   setlength(s2,length(s1)+2);
   sepNum(s1,s2);
repeat
   sf1(s2);    // * /
   ps(s2);
   sf2(s2);    // + -
   ps(s2);
   sf3(s2);
   ps(s2);
until  s2[2]='';    //是否还有括号
edit1.Text:=s2[1];
end;
2010-03-02 18:41
快速回复:如何实现混合运算(89-3*2+(54-42)/3)?
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.017632 second(s), 9 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved