Урок 22 Задача 8
Primary tabs
"Калькулятор":
Напишите функцию, которая получает на вход произвольную строку вида:5*(3+4)-7*9+3*(2+(2-7))
(арифметическое выражение со скобками любого уровня вложенности и операциями умножения,
вычитания и сложения)и в качестве ответа возвращает результат этого выражения.
Рекомендация: сначала убедитесь, что число открывающих скобок равно числу закрывающих.
Функция raskr_skob находит выражение, заключённое в скобки, копирует его в подстроку, отправляя затем в процедуру, которая раскладывает её на числа и знаки, формируя два массива. Эти массивы отправляются в функцию, которая считает результат выражения и переводит этот результат в строковый тип, возвращая его. Функция raskr_skob вставляет это значение вместо того, что было в скобках. Из-за множественной вложенности после цикла остаётся вероятность, что не все скобки раскрыты.
Тогда функция вызывает саму себя. Когда скобок в выражении не остаётся, клиентский код отправляет оставшуюся строку на вычисление уже без рекурсии
type intArr = array[1..100] of integer; chArr = array[1..99] of char; var a : intarr; z : chArr; st: string; ai, zi: integer; //предельные индексы получившихся массивов procedure getData(subst: string; var a : intarr; var z : chArr; var ai, zi: integer); var s : string; j: integer; begin s := ''; zi := 0; ai := 0; for j := low(a) to high(a) do a[j] := 0; for j := low(z) to high(z) do z[j] := #0; j := 1; while j <= length(subst) do begin while (subst[j] >= '0') and (subst[j] <= '9') do begin s := s + subst[j]; j += 1; end; if (s <> '') then begin ai += 1; val(s, a[ai]); s := ''; end; if j > length(subst) then break; if (subst[j] < '0') or (subst[j] > '9') then begin zi += 1; z[zi] := subst[j]; j += 1; if (subst[j] < '0') or (subst[j] > '9') then begin //если следом отрицательное число. Чтобы минус попал // в числа, а не в символы. Напр: "5+-2" s := s + subst[j]; j += 1; end; end; end; end; function calculate(a : intarr; z : chArr; ai, zi: integer): string; var i , j, res : integer; begin i := 1; while i <= zi do begin if z[i] = '*' then begin a[i] := a[i] * a[i+1]; for j := (i + 1) to ai-1 do a[j] := a[j+1]; a[ai] := 0; for j := i to zi-1 do z[j] := z[j+1]; z[zi] := #0; end else i += 1; end; res := a[1]; for i := 1 to zi do if z[i] = '-' then res := res - a[i+1] else res := res + a[i+1]; str(res, result); end; function raskr_skob(var st: string ): string; var subst: string; i, ind, count: integer; open_skob: boolean; begin for i := 1 to length(st) do begin if st[i] = '(' then begin ind := i; count := 1; open_skob := true; end; if (st[i] = ')') and open_skob then begin subst := Copy (st, ind+1, count-2); //чтобы копировать строку без скобок Delete (st, ind, count); getData(subst, a, z, ai, zi); subst := calculate(a, z, ai, zi); Insert (subst, st, ind); open_skob := false; end; count += 1; end; for i := 1 to length(st) do if st[i] = '(' then raskr_skob(st); end; begin st := '5*(3+(2+(3-1)))-7*9+3*(2+(2-7))'; write(st); raskr_skob(st); getData(st, a, z, ai, zi); writeln('= ', calculate(a, z, ai, zi)); readln(); end.
- Log in to post comments
- 1095 reads
vedro-compota
Wed, 07/12/2023 - 20:47
Permalink
1) Решаем без массивов
1) Решаем без массивов
2) Основная функция должна быть быть рекурсивной, принимать на выход строку и возвращать число (ответ на выражение) -- это же относится к предыдущей задаче (вычисление "плоского" выражения без скобок - лучше начать с нее и опубликовать).
_____________
матфак вгу и остальная классика =)
piliugin
Sat, 07/15/2023 - 15:41
Permalink
Без массивов
piliugin
Wed, 07/19/2023 - 17:11
Permalink
Исправил