Урок 21 Задача 8
Primary tabs
"Калькулятор":
Напишите функцию, которая получает на вход произвольную строку вида:5*(3+4)-7*9+3*(2+(2-7))(арифметическое выражение со скобками любого уровня вложенности и операциями умножения, вычитания и сложения)
и в качестве ответа возвращает результат этого выражения.
Рекомендация: сначала убедитесь, что число открывающих скобок, равно числу закрывающих.
type
massivStrok = array[1..1000] of string;
var
s: string;
stroki: massivStrok;
{функция получает на вход массив строк,
смещает пустые элементы массива влево (за один проход),
возвращает смещенный массив}
function sdvig(stroki: massivStrok; i: integer): massivStrok;
var
x: integer;
begin
x:= 1;
while not(stroki[i+1] = 'N') do
begin
if stroki[i] = '' then
begin
if stroki[i-x] = '' then
begin
x:= x + 1
end else begin
stroki[i]:= stroki[i-x];
stroki[i-x]:= '';
end;
end;
if not (stroki[i] = '') then
i:= i-1;
end;
result:= stroki;
end;
{функция получает на вход цифру,
возвращает запись цифры в строковом виде}
function preobr (a: integer): string;
var
s: string;
begin
if a = 1 then
s:='1'
else if a = 2 then
s:='2'
else if a = 3 then
s:='3'
else if a = 4 then
s:='4'
else if a = 5 then
s:='5'
else if a = 6 then
s:='6'
else if a = 7 then
s:='7'
else if a = 8 then
s:='8'
else if a = 9 then
s:='9'
else
s:='0';
result:= s;
end;
{функция получает на вход число,
возвращает запись числа в строковом виде}
function chislo (a: integer): string;
var
b, d, x, h, i: integer;
n: string;
begin
if a < 0 then
begin
n:= n + '-';
a:= -1*a;
end;
b:= a;
d:=1;
h:=1;
while not (b div 10 = 0) do
begin
b:= b div 10;
d:= d*10;
h:= h+1;
end;
for i:=1 to h do
begin
x:= a div d;
a:= a mod d;
d:= d div 10;
n:= n + preobr(x);
end;
result:= n;
end;
{функция выполняет арифметические действия в границах скобок
либо в границах всего выражения, если скобок нет}
function dejstvie(stroki: massivStrok; i: integer): massivStrok;
var
a, b, m: integer;
q: boolean;
begin
q:= true;
m:= i;
while not ((stroki[m-2] = '(') or (stroki[m-2] = 'N')) do
begin
if (stroki[i] = '(') or (stroki[i] = 'N') then
q:= false;
if (stroki[i] = '*') or ((stroki[i] = '+') or (stroki[i] = '-')) and (q=false) then
begin
val(stroki[i-1], a);
val(stroki[i+1], b);
if stroki[i] = '*' then
a:= a*b
else if stroki[i] = '+' then
a:= a+b
else if stroki[i] = '-' then
a:= a-b;
stroki[i]:= chislo(a);
stroki[i-1]:= '';
stroki[i+1]:= '';
stroki:= sdvig(stroki, i+1);
end else
if q = false then
i:= i+1
else
i:= i-1;
end;
if (stroki[m-2]='(') and (stroki[m]=')') then
begin
stroki[m-2] := '';
stroki[m] := '';
stroki:= sdvig(stroki, m);
end;
result:= stroki;
end;
{рекурсия}
function skobki(stroki: massivStrok; i: integer): massivStrok;
begin
if (stroki[i] = 'K') then
result := dejstvie(stroki, i)
else
if stroki[i] = ')' then
result := skobki(dejstvie(stroki, i), i)
else
result:= skobki(stroki, i+1);
end;
{функция перезаписывает строку в массив строк,
где каждый элемент - это либо число,
либо знак действия,
либо скобка}
function perezapis(s: string): integer;
var
i, j: integer;
stroki: massivStrok;
begin
i:= 0;
j:= 1;
stroki[1]:= 'N';
while (i < length(s)) do
begin
i:= i+1;
if (s[i]>='0')and(s[i]<='9')
or (s[i]='*') or (s[i]='+') or (s[i]='-')
or (s[i]='(') or (s[i]=')') then
begin
j:= j+1;
if (s[i]>='0')and(s[i]<='9') then
begin
for i:= i to length(s) do
begin
if (stroki[j-1] = '-') and ((j = 3) or (stroki[j-2] = '(')) then
j:= j-1;
stroki[j]:= stroki[j] + s[i];
if not ((s[i+1]>='0')and(s[i+1]<='9')) then
break;
end;
end else
stroki[j]:= s[i];
if (j>4) and (stroki[j-3]='(') and (stroki[j-2]='-')and (stroki[j]=')') then
begin
stroki[j-3]:='-' + stroki[j-1];
stroki[j-2]:='';
stroki[j-1]:='';
stroki[j]:='';
j:= j-3;
end;
end;
end;
stroki[j+1]:= 'K';
stroki:= skobki(stroki, 1);
val(stroki[j], result);
end;
begin // тело основной программы
s:= '5*(3-4)-7*(9-3)*(2*(2-7*(5-9)))';
writeln(perezapis(s));
readln();
end.- Log in to post comments
- 1494 reads
vedro-compota
Sun, 01/29/2023 - 13:29
Permalink
Добавить решение с
Добавить решение с использованием базовой функции, которая просто возвращает int
_____________
матфак вгу и остальная классика =)
Patrick
Sat, 02/04/2023 - 11:41
Permalink
var
var s: string; function kalkulyator (s: string; i: integer): integer; var n: string; a, b, x, j: integer; znak1, znak2: char; chislo1, chislo2, umnozhenie, skobki, k: boolean; begin n:= ''; znak1:= ' '; znak2:= ' '; chislo1:= false; chislo2:= false; umnozhenie:= false; skobki:= false; k:= false; j:= 0; while not k do // цикл для обхода строки begin i:= i+1; if not skobki then begin if (s[i]>='0')and(s[i]<='9') or (s[i] = '(') then // если встретилось число или откр. скобка begin if (s[i]>='0')and(s[i]<='9') then begin for i:= i to length(s) do begin n:= n + s[i]; if not ((s[i+1]>='0')and(s[i+1]<='9')) then break; end; val(n, x); n:= ''; end else begin skobki:= true; x:= kalkulyator(s, i); // рекурсивный вызов end; if umnozhenie then begin if chislo2 then b:= b*x else a:= a*x; umnozhenie:= false; end else begin if chislo1 then begin b:= x; chislo2:= true; end else begin a:= x; if znak1 = '-' then a:= 0-a; chislo1:= true; end; end; end else if (s[i] = '+') or (s[i] = '-') or (s[i] = '*')then // если встретился знак if (s[i] = '+') or (s[i] = '-') then // если плюс или минус begin if chislo2 then znak2:= s[i] else znak1:= s[i]; end else // если умножение umnozhenie:= true; end; if skobki then begin if s[i] = '(' then j:= j+1 else if s[i] = ')' then j:= j-1; end; if (s[i] = ')') and (not skobki) or (i=length(s)) then k:= true else if (j = 0) and (skobki) then skobki:= false; if chislo2 and (not (znak2 = ' ') or k) then begin if znak1 = '+' then a:= a+b else a:= a-b; znak1:= znak2; znak2 := ' '; chislo2 := false; end; end; result:= a; end; begin s:= '5*(3+4)-7*9+3*(2+(2-7))'; // s:= '5-((-147+147)+7)*5'; // s:= '-10*(3-(-4))'; // s:= '-12-(-5)'; // s:= '5*(3-4)-7*(9-3)*(2*(2-7*(5-9)))'; // s:= '3*(-6)'; // s:= '-(-450)'; // s:= '-77'; writeln (kalkulyator(s, 0)); readln(); end.