Задача №8 Урок №22

"Калькулятор":
Напишите функцию, которая получает на вход произвольную строку вида:

5*(3+4)-7*9+3*(2+(2-7))

(арифметическое выражение со скобками любого уровня вложенности и операциями умножения, вычитания и сложения)

и в качестве ответа возвращает результат этого выражения.

Рекомендация: сначала убедитесь, что число открывающих скобок, равно числу закрывающих.

Решение:

var
  s: string;
  i: integer;

 function arithmetic(num1,num2: integer; oper1: string): integer;
  begin
     case oper1 of
      '+': num1 := num1 + num2;
      '-': num1 := num1 - num2;
      '*': num1 := num1 * num2;
    end;
    result := num1;
  end; 

  function calc(var i: integer; s: string): integer;
  var Code,num2,num3,num1,n1: integer; oper1,oper2, numstr1, numstr2, numstr3: string;
  begin
    n1:=0;
    num1:= 0;
    num2:= 0;
    num3:= 0;
    oper1:='';
  while(i <= length(s)) do
  begin
    if n1<> 0 then
    begin
      if (s[i]<>'*') then
      begin
        num1:= arithmetic(n1,num1,oper1);
        n1:=0;
        oper1:='';
      end
      else
      begin
        num2:= num1;
        num1:= n1;
        n1:= 0;
      end;
    end;
    if (s[i]>= '0') and (s[i] <= '9') then
    begin
      if (num1 = 0) then
      begin
        numstr1:= s[i];
        val(numstr1,num1,Code);
        if ((i=length(s)) and (n1 <> 0)) then
          n1:= arithmetic(n1,num1,oper1);
      end
      else
      begin
        numstr2:= s[i];
        val(numstr2,num2,Code);
        if (i = length(s))or(oper1 = '*')or(s[i+1]= ')') then
        begin
          num1:= arithmetic(num1,num2,oper1);
          num2:= 0;
          oper1:= '';
          if (s[i+1]=')')then
          begin
            if (i+1<>length(s)) then
              inc(i);
            break;
          end;
        end;
      end;
    end
    else if(s[i] = '(') then
    begin
      if i<>1 then
        n1:= num1;
      inc(i);
      num1:= calc(i,s);
    end
    else if(s[i] = ')') then
    begin
      if i = length(s) then
        dec(i);
      if num2<>0 then
        num1:= arithmetic(num1,num2,oper1);
      num2:= 0;
      oper1:= '';
      break;
    end
    else if (oper1 = '') then
      oper1:= s[i]
    else
    begin
      oper2:= s[i];
      if (oper2 <> '*') then
      begin
        num1:= arithmetic(num1,num2,oper1);
        numstr2:='';
        oper1:= oper2;
        oper2:= '';
        num2:=0;
      end
      else
      begin
        if(s[i+1] <> '(') then
        begin
          inc(i);
          numstr3:= s[i];
          val(numstr3,num3,Code);
          num2:= arithmetic(num2,num3,oper2);
          num3:= 0;
          oper2:= '';
          num1:= arithmetic(num1,num2,oper1);
          num2:= 0;
          oper1:= '';
          break;
        end
        else
        begin
          inc(i,2);
          num3:= calc(i,s);
          num2:= arithmetic(num2,num3,oper2);
          num3:= 0;
          oper2:= '';
          if (i = length(s)) then
          begin
            num1:= arithmetic(num1,num2,oper1);
            num2:= 0;
            oper1:= '';
          end;
        end;
        end;
      end;
      inc(i);
    end;
    if n1 = 0 then
      result:= num1
    else
      result:= n1;
  end;

  begin
    i:= 1;
    s:= '5*(3+4)-7*9';
    write(s);
    write(' = ',calc(i,s));
    readln();
  end.