Урок 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
- 1581 reads
vedro-compota
Wed, 07/12/2023 - 20:47
Permalink
1) Решаем без массивов
1) Решаем без массивов
2) Основная функция должна быть быть рекурсивной, принимать на выход строку и возвращать число (ответ на выражение) -- это же относится к предыдущей задаче (вычисление "плоского" выражения без скобок - лучше начать с нее и опубликовать).
_____________
матфак вгу и остальная классика =)
piliugin
Sat, 07/15/2023 - 15:41
Permalink
Без массивов
var s: string; i: integer; function getSumm(a, b: integer): integer; begin result := b + a; end; function getMult(var a: integer; b: integer; var mult: boolean): integer; begin result := a * b; mult := false; end; function TakeResult(var i: integer; s: string): integer; var str: string; a, midres: integer; minus, mult: boolean; begin minus := false; mult := false; result := 0; repeat i += 1; if (s[i] >= '0') and (s[i] <= '9') then str := str + s[i] else begin if s[i] = '(' then begin a := TakeResult(i, s); i += 1; end else val(str, a); if minus = true then begin a := a*(-1); minus := false; end; if mult = true then a := getMult(a, midres, mult); if s[i] = '*' then begin mult := true; midres := a; end else result := getSumm(a, result); if s[i] = '-' then minus := true; str := ''; end; until (s[i] = ')') or (i > length(s)); end; begin i := 0; s := '5*(3+(2*2-(2+2)))+7*9+3*(2+(2-7))+5'; writeln(s,' = ', TakeResult(i, s)); readln(); end.piliugin
Wed, 07/19/2023 - 17:11
Permalink
Исправил
var s: string; i: integer; function TakeResult(var i: integer; s: string): integer; var str: string; a, midres: integer; minus, mult: boolean; begin minus := false; mult := false; result := 0; repeat i += 1; if (s[i] >= '0') and (s[i] <= '9') then str := str + s[i] else begin if s[i] = '(' then begin a := TakeResult(i, s); i += 1; end else val(str, a); if minus = true then begin a := a*(-1); minus := false; end; if mult then begin a := a * midres; mult := false; end; if s[i] = '*' then begin mult := true; midres := a; end else result := result + a; if s[i] = '-' then minus := true; str := ''; end; until (s[i] = ')') or (i > length(s)); end; begin i := 0; s := '5*(3+(2*2-(2+2)))+7*9+3*(2+(2-7))+5'; writeln(s,' = ', TakeResult(i, s)); readln(); end.