Задача 8 урок 21

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

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

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

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

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

Не верное решение
//вычисление

function culc(s: string): string;
var n, n1, i, code, otv: integer;
    s1,ch: string;
    flag1,flag2: boolean;
begin
  s := s + ' ';
  ch := '';
  flag1 := false;
  flag2 := false;
  for i := 1 to length(s) do  
    begin
      if ((s[i] >= '0') and (s[i] <= '9')) then
        ch := ch + s[i]
      else
        begin
          val(ch, n, code);
          ch := '';
          // действие зависит от флага
          if flag1 then
          begin
            n := n * n1;
            flag1 := false;
          end;
          if flag2 then
          begin
            n := n * (-1);
            flag2 := false;
          end;
          // условия изменения флага
          if s[i] = '*' then
          begin
            flag1 := true;
            n1 := n; // сохранить число для операции умножения
          end
          else
          begin
            if  s[i] = '-' then
              flag2 := true;
            otv := otv + n;     
          end;                  
        end;
     end;
     str(otv, s1);
     result := s1;
end;

//обход по скобкам
function obhod(s: string):string;

//перезапись
procedure perezap(st: string; l,p: integer; var s:string);
var i: integer;
    s1, s2: string;
begin
  for i:= 1 to l -1 do 
    s1 := s1 +s [i];
  for i := p +1 to length(s) do
    s2 := s2 + s[i];
  s := s1 + st + s2;
  writeln(s);
end;

var i, l, p: integer;
    st: string;
    rez: string;
begin
  st := '';
  for i := 1 to length(s) do
    if s[i] = ')' then
    begin
      p := i;
      break;
    end;
  for i := p downto 1 do
    if s[i] = '(' then
    begin
      l := i;
      break;
    end;
      for i := l + 1 to p - 1 do
        st := st + s[i];
      writeln(st);
      rez := culc(st);
      perezap(rez,l,p,s);
      result := s;
end;
var s: string;
begin
  s:= '(1+4+(1+5))+20';
  writeln(obhod(s));
end.

Консоль

(1+4+-4)+20

function culc(s: string): integer;

var n, n1, i, code, otv: integer;
    s1,ch,newstr: string;
    flag1, flag2, skobkaflag, skobkaend: boolean;

begin
  s := s + ' ';
  ch := '';
  flag1 := false;
  flag2 := false;
  skobkaflag :=false;
  skobkaend := false;
  otv := 0;
  newstr := '';
  for i := 1 to length(s) do  //подача строки
    begin                     //сначала проверить скобки, чтобы пустить запись строки в newstr
      if s[i]=')' then
      begin
        skobkaflag := false;
        skobkaend := true;
      end
      else
      if skobkaflag = true then
       newstr := newstr + s[i]
      else if ((s[i] >= '0') and (s[i] <= '9')) then
        ch := ch + s[i]
      else if s[i]='(' then
        skobkaflag := true
      else
        begin
          val(ch, n, code);
          ch := '';
          if skobkaend = true then    //если скобка зарылась, то работаем с содержимым
          begin
             skobkaend := false;
             n := culc(newstr);
          end;
          // действие зависит от флага
          if flag1 then
          begin
            n := n * n1;
            flag1 := false;
          end;
          if flag2 then
          begin
            n := n * (-1);
            flag2 := false;
          end;
          // условия изменения флага
          if s[i] = '*' then
          begin
            flag1 := true;
            n1 := n; // сохранить число для операции умножения
          end
          else
          begin
            if  s[i] = '-' then
              flag2 := true;
            otv := otv + n;
          end;
        end;
     end;
     culc := otv;
end;

var s: string;
begin
  s:= '5+(10-5)*3+(2*(2+3))';
  writeln(culc(s));
  readln
end. 
vedro-compota's picture

     val(ch, n, code);
          ch := '';
          if skobkaend = true then    //если скобка зарылась, то работаем с содержимым
          begin
             skobkaend := false;
             n := culc(newstr);
          end;
          // действие зависит от флага
          if flag1 then
          begin
            n := n * n1;
            flag1 := false;
          end;
          if flag2 then
          begin
            n := n * (-1);
            flag2 := false;
          end;
          // условия изменения флага
          if s[i] = '*' then
          begin
            flag1 := true;
            n1 := n; // сохранить число для операции умножения
          end
          else
          begin
            if  s[i] = '-' then
              flag2 := true;
            otv := otv + n;
          end;

-- лучше вынести в отдельную подпрограмму

_____________
матфак вгу и остальная классика =)