Задание 8 Урок 22
Primary tabs
Напишите функцию, которая получает на вход произвольную строку вида:
5*(3+4)-7*9+3*(2+(2-7))(арифметическое выражение со скобками любого уровня вложенности и операциями умножения, вычитания и сложения)
и в качестве ответа возвращает результат этого выражения.
uses SysUtils; type DataRecord = record I, Sum : Integer; end; var temp1, temp2, temp3, znak: string; flag1, flag2: boolean; intChislo, intChislo1, intChislo2, intChislo3, Code, sumTemp: integer; S :string; N :integer; Data: DataRecord; function calc(Data: DataRecord; s: string; i, sum: integer): DataRecord; var temp1, temp2, temp3, znak: string; flagNextMultTwoMember, flagNextMultMultipleMember, flagBracketPlus, flagBracketMult: boolean; intChislo, intChislo1, intChislo2, intChislo3, Code, multTemp: integer; begin multTemp := 0; // временная сумма (для слагаемых типа ...a*b*c*...) // если только слагаемые то используем temp1 (каждое слагаемое помещаем в temp1 и увеличиваем общую сумму sum += temp1) // если слагаемые состоят максимум из 2х множителей то temp1 и temp2 // если слагаемое состоит из более чем 2х множителей (...a*b*c*d...) то используем 3 temp переменных: // предыдущие множители (a*b*c*...) на каждой итерации становятся multTemp, и умножаются на temp3 // 1) multTemp = temp1 * temp2 // 2) multTemp *= temp3 // 3) goto 2) temp1 := ''; temp2 := ''; temp3 := ''; flagNextMultTwoMember := true; // флаг для перехода в случае 2х множителей в слагаемом flagNextMultMultipleMember := true; // флаг для перехода в случае более 2х множителей в слагаемом flagBracketPlus := false; // флаг для перехода перед скобкой при сложении flagBracketMult := false; // флаг для перехода перед скобкой при умножении znak := ''; // знак перед числом while (i < (length(s)+1)) do // итерируем по выражению до конца begin if((s[i-1] = ')')) then // выходим из закрывающей скобки (из функции) begin break; end else begin if (i > 1) then // проверяем знак перед слагаемым begin if (s[i-1]='-')or(s[i-1]='+') then // и есть ли он вообще begin znak := s[i-1]; end; end; if(s[i]='(') then // если встречаем скобку то рекурсивно вызываем функцию begin if(s[i-1]='*') then begin flagBracketMult := true; end else begin flagBracketPlus := true; end; i := i + 1; if(flagBracketMult) then // умножение перед скобкой !!! не работает !!! begin Data := calc(Data, S, i, 0); i := Data.I+1; Val(temp2, intChislo1, Code); temp2 := IntToStr(Data.Sum); Val(znak + temp1, intChislo1, Code); Val(temp2, intChislo2, Code); sum := sum + intChislo1 * intChislo2; // увеличиваем общую сумму на произведение 2х предыдущих множителей //сброс параметров temp1 := ''; temp2 := ''; temp3 := ''; flagNextMultTwoMember := true; flag2 := true; flagBracketPlus := false; flagBracketMult := false; znak := ''; continue; end else begin Data := calc(Data, S, i, 0); // получили после рекурентного вызова функции позицию и сумму в скобках if(s[i-2] = '+') then sum := sum + Data.Sum else sum := sum - Data.Sum; i := Data.I+1; continue; end; end; if (flagNextMultTwoMember) then begin temp1 := temp1 + s[i]; //заполняем 1 временное число Val(s[i+1], intChislo, Code); // смотрим на следующий символ if (Code = 0) then // если это цифра то добавляем в temp1 и переходим к следующему символу begin i := i + 1; continue; end else begin if (s[i+1] <> '*') then // если это + или - (множитель ..a*b*c*... закончился ) begin Val(znak + temp1, intChislo1, Code); sum := sum + intChislo1; // увеличиваем общую сумму на накопленное число temp1 учитывая знак перед ним end else // если это умножение то идем дальше begin flagNextMultTwoMember := false; // переходим ко второму временному множителю \/ i := i + 2; // \/ continue; // \/ end // \/ end // \/ end // \/ else // \/ begin // переходим ко второму временному множителю if (flagNextMultMultipleMember) then begin temp2 := temp2 + s[i]; //заполняем 2 временное число Val(s[i+1], intChislo, Code); if (Code = 0) then // если число то добавляем в temp2 и переходим к следующему символу begin i := i + 1; continue; end else begin if (s[i+1] <> '*') then // если это + или - (множитель ..a*b*c*... закончился) begin Val(znak + temp1, intChislo1, Code); Val(temp2, intChislo2, Code); sum := sum + intChislo1 * intChislo2; // увеличиваем общую сумму на произведение 2х предыдущих множителей end else // если это * (множитель ..a*b*c*... НЕ закончился) begin Val(znak + temp1, intChislo1, Code); Val(temp2, intChislo2, Code); multTemp := intChislo1 * intChislo2; // делаем временную сумму предыдущих множителей flagNextMultMultipleMember := false; // переходим ко третьему временному множителю \/ i := i + 2; // \/ continue; // \/ end // \/ end // \/ end // \/ else // переходим ко третьему временному множителю begin temp3 := temp3 + s[i]; //заполняем 3 временное число Val(s[i+1], intChislo, Code); if (Code = 0) then // если число то добавляем в temp3 и переходим к следующему символу begin i := i + 1; continue; end else begin if (s[i+1] = '*') then // если это * (множитель ..a*b*c*... НЕ закончился) begin Val(temp3, intChislo3, Code); multTemp := multTemp * intChislo3; // увеличиваем временную накопительную переменную (произведение) temp3 := ''; i := i + 2; continue; end else // если это + или - (множитель ..a*b*c*... закончился) begin Val(temp3, intChislo3, Code); Val(znak+temp1, intChislo1, Code); multTemp := multTemp * intChislo3; // увеличиваем временную накопительную переменную (произведение) sum := sum + multTemp ; // увеличиваем общую сумму end end end end; temp1 := ''; // сброс (например, множитель ..a*b*c*... закончился) temp2 := ''; temp3 := ''; flagNextMultTwoMember := true; flagNextMultMultipleMember := true; flagBracketPlus := false; // флаг для перехода перед скобкой flagBracketMult := false; znak := ''; i := i + 2; // мы переходим через знак и число (....1+2*3...)+2 end; end; Data.I := i; Val(temp1, intChislo, Code); Data.Sum := sum + intChislo; result := Data; end; begin S := '5*(3+4)'; Data := calc(Data, S, 1, 0); writeln(S, ' = ', Data.Sum); S := '7*9'; Data := calc(Data, S, 1, 0); writeln(S, ' = ', Data.Sum); S := '3*(2+(2-7))'; Data := calc(Data, S, 1, 0); writeln(S, ' = ', Data.Sum); S := '5*(3+4)-7*9+3*(2+(2-7))'; Data := calc(Data, S, 1, 0); writeln(S, ' = ', Data.Sum); S := '5*(3+4)-7*9+3*(2+(2-7))+1'; Data := calc(Data, S, 1, 0); writeln(S, ' = ', Data.Sum); S := '5*(3+4)-7*9+3*(2+(2-7))-1*1*(1+1)'; Data := calc(Data, S, 1, 0); writeln(S, ' = ', Data.Sum); end.
консоль:
5*(3+4) = 35 7*9 = 63 3*(2+(2-7)) = -9 5*(3+4)-7*9+3*(2+(2-7)) = -37 5*(3+4)-7*9+3*(2+(2-7))+1 = -36 5*(3+4)-7*9+3*(2+(2-7))-1*1*(1+1) = -39
- Log in to post comments
- 271 reads