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

Урок 21

Напишите функцию, которая получает на вход произвольную строку вида:
5*(3+4)-7*9+3*(2+(2-7))
(арифметическое выражение со скобками любого уровня вложенности и
операциями умножения, вычитания и сложения)
и в качестве ответа возвращает результат этого выражения.
Рекомендация: сначала убедитесь, что число открывающих скобок,
равно числу закрывающих.


 var
   loopCount, count1: integer;
   inputString: string;

function expression(inputString: string): integer;
  var
     loopCount, errorCode: integer;
     stringToInt, lastCh: string;
     flag1, flagChar: boolean;
     newInt1, multInt: integer;

  begin
   //WriteLn('Проверка захода експрешн');
   newInt1 := 0;
   multInt := 0; //число для следующего умножения с newInt1
   expression := 0;
   flagChar := false;
   flag1 := false; //флаг умножения
   stringToInt := ''; // строка для получения числа
   lastCh := '+'; //память на последние + и -
   for loopCount := 1 to length(inputString) do //прохожу по строке
   begin
     //ищу число
     if (inputString[loopCount] >= '0') and (inputString[loopCount] <= '9') then
     begin
         if flagChar and (inputString[loopCount - 1] = '-') then
         begin
            stringToInt := stringToInt + '-' + inputString[loopCount];//если сейчас число, а был минус и флаг не сброшен
            //отправляем строку с минусом в val
            flagChar := false;
         end
         else
            stringToInt := stringToInt + inputString[loopCount]; //добавляю цифру в числовую строку
     end
     else if (inputString[loopCount - 1] = '*') and (inputString[loopCount] <> '*') then
        flagChar := true
     else //если не цифра, а знак
     begin
       //  if not flagChar then
         //begin
            val(stringToInt, newInt1, errorCode); //получаем число из прошлого набора цифр
            stringToInt := '';
            if flag1 then //если проходили знак * перед последним числом
            begin
              newInt1 := newInt1 * multInt;
              flag1 := false;
            end;
            if inputString[loopCount] = '*' then // если сейчас знак *, то запоминаем число
            begin
              multInt := newInt1; //запомнили
              flag1 := true; //надо умножить в след раз
            end
            else //если сейчас не знак умножения,
            // то получаем результат от предыдущего + или -
            begin
              if lastCh = '+' then // +
              begin
                expression := expression + newInt1;
              end
              else // -
              begin
                expression := expression - newInt1;
              end;
              if (inputString[loopCount] = '-') and flag1 then //если сейчас -, а прошлый знак * и умножение не сброшено,
               //то есть число с минусом будет - то мы оставляем +
                 lastCh := '+'
              else
                lastCh := inputString[loopCount]; // если сейчас + или -, то запоминаем
            end;
         //end;
      end;
     end;

       // блок для отработки последнего числа и конечного результата
       val(stringToInt, newInt1, errorCode);
       if flag1 then
       begin
         newInt1 := newInt1 * multInt;
         flag1 := false;
       end;
       if lastCh = '+' then //отработка последнего числа
       begin
         expression := expression + newInt1;
       end
       else
       begin
         expression := expression - newInt1;
       end;
   //writeln('Ответ: ', expression);
 end;


function change(string1: string; loopCount1: integer): string;
  var string2: string;
      loopCount2, count1, fromExpression: integer;

begin
  //WriteLn('Проверка захода чендж');
  count1 := 1;
  string2 := '';
  loopCount2 := loopCount1 + 1;
  while (count1 <> 0) do
  begin
    if (string1[loopCount2] = '(') then
    begin
      inc(count1);
    end
    else if (string1[loopCount2] = ')') then
      count1 := count1 - 1;
    inc(loopcount2);
  end;
  loopCount2 := loopCount2 - 1;
  string2 := Copy(string1, loopCount1 + 1, loopCount2 - loopCount1 - 1);
  Delete(string1,loopCount1, loopCount2 - loopCount1 + 1);

  for loopCount2 := 1 to length(string2) do
  begin
    if string2[loopCount2] = '(' then
      string2 := change(string2, loopCount2);
  end;
  fromExpression :=expression(string2);
  str(fromExpression, string2);
  Insert(string2,string1,loopCount1);
  change := string1;
end;


begin
   count1 := 0;
   writeln('Введите строку');
   // readln(inputString); //закоментил для отладки
   inputString := '5*(3-4)-7*(9-3)*(2*(2-7*(5-9)))';
   writeln('Введенная строка: ', inputString);

  for loopCount := 1 to length(inputString) do
  begin
    if inputString[loopCount] = '(' then
        count1 := count1 + 1
    else if inputString[loopCount] = ')' then
        count1 := count1 - 1;
  end;
  if count1 = 0 then
  begin
    for loopCount := 1 to length(inputString) do
    begin
      if inputString[loopCount] = '(' then
        inputString := change(inputString, loopCount);
    end;
    writeln('Результат: ', expression(inputString));
  end
  else
    writeln('Ошибка: убедитесь, что число открывающих скобок, равно числу закрывающих');
  readln();
end.

КОНСОЛЬ

Введите строку
Введенная строка: 5*(3+4)-7*9+3*(2+(2-7))
Результат: -37
vedro-compota's picture

засчитано

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