Задача 8 Урок 21
Primary tabs
Напишите функцию, которая получает на вход произвольную строку вида:
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
- Log in to post comments
- 1372 reads
vedro-compota
Sun, 01/09/2022 - 13:17
Permalink
засчитано
засчитано
_____________
матфак вгу и остальная классика =)
vedro-compota
Thu, 09/24/2026 - 21:21
Permalink
qwen3:14b
Код, предоставленный в вопросе, содержит несколько серьёзных ошибок, которые необходимо
исправить для корректной работы программы. Ниже приведены основные проблемы и предложения
по их исправлению.
---
### **Основные ошибки в коде:**
#### 1. **Некорректная обработка приоритета операций**
Функция `expression` не учитывает порядок выполнения операций (умножение должно
выполняться раньше сложения и вычитания). Это приведёт к неправильным результатам,
например, для выражения `5 + 3 * 4` будет вычислено как `(5 + 3) * 4 = 32`, вместо
правильного `5 + (3 * 4) = 17`.
**Решение:**
Использовать стек для вычисления выражения с приоритетом операций (например, преобразовать
выражение в постфиксную нотацию (Обратная польская запись)).
---
#### 2. **Некорректная обработка отрицательных чисел и минусов**
В коде попытка обработки чисел с минусом не корректна. Например, выражение `5 - (3 + 4)`
может не распознаваться правильно, потому что код не учитывает минус как оператор
вычитания, а не как часть числа.
**Решение:**
Во время разбора строки нужно различать минус как оператор и как часть числа (например,
отрицательное число). Это требует дополнительной логики для определения контекста минуса.
---
#### 3. **Ошибка в переменных: регистр и имена**
В коде используются переменные с разным регистром (например, `loopcount2` и `loopCount2`),
что может вызвать ошибки компиляции в Pascal, где регистр важен. Также, в функции `change`
переменная `loopcount2` используется, но не объявлена.
**Решение:**
Исправить имена переменных на единый стиль (например, `loopCount2`) и убедиться, что все
переменные объявлены.
---
#### 4. **Некорректная обработка скобок**
Функция `change` предназначена для раскрытия скобок, но её реализация может не корректно
обрабатывать вложенные скобки. Например, вложенные скобки могут не заменяться на
результаты вычисления.
**Решение:**
Убедиться, что функция `change` рекурсивно обрабатывает вложенные скобки. Также проверить,
правильно ли заменяется подстрока на результат вычисления.
---
### **Рекомендации по исправлению кода:**
#### **1. Исправление функции `expression` (приоритет операций):**
Вместо текущей реализации, используйте стек или преобразование в постфиксную нотацию.
Пример реализации:
```pascal
function expression(inputString: string): integer;
var
stack: array of char;
i: integer;
num: integer;
op: char;
begin
// Реализация с использованием стека (пример)
// ...
end;
```
---
#### **2. Исправление функции `change` (раскрытие скобок):**
Убедитесь, что функция `change` корректно обрабатывает вложенные скобки. Пример:
```pascal
function change(string1: string; loopCount1: integer): string;
var
count1, loopCount2: integer;
string2: string;
fromExpression: integer;
begin
count1 := 1;
loopCount2 := loopCount1 + 1;
while count1 > 0 do
begin
if string1[loopCount2] = '(' then
inc(count1)
else if string1[loopCount2] = ')' then
dec(count1);
inc(loopCount2);
end;
loopCount2 := loopCount2 - 1;
string2 := Copy(string1, loopCount1 + 1, loopCount2 - loopCount1 - 1);
fromExpression := expression(string2);
Delete(string1, loopCount1, loopCount2 - loopCount1 + 1);
Insert(IntToStr(fromExpression), string1, loopCount1);
change := string1;
end;
```
---
#### **3. Исправление переменных и регистров:**
Убедитесь, что все переменные объявлены и используются с одинаковым регистром. Например,
`loopCount2` вместо `loopcount2`.
---
### **Пример исправленного кода:**
```pascal
function expression(inputString: string): integer;
var
stack: array of char;
i, num: integer;
op: char;
begin
// Реализация с использованием стека и приоритетом операций
// ...
end;
function change(string1: string; loopCount1: integer): string;
var
count1, loopCount2: integer;
string2: string;
fromExpression: integer;
begin
count1 := 1;
loopCount2 := loopCount1 + 1;
while count1 > 0 do
begin
if string1[loopCount2] = '(' then
inc(count1)
else if string1[loopCount2] = ')' then
dec(count1);
inc(loopCount2);
end;
loopCount2 := loopCount2 - 1;
string2 := Copy(string1, loopCount1 + 1, loopCount2 - loopCount1 - 1);
fromExpression := expression(string2);
Delete(string1, loopCount1, loopCount2 - loopCount1 + 1);
Insert(IntToStr(fromExpression), string1, loopCount1);
change := string1;
end;
begin
// Основная часть программы
// ...
end.
```
---
### **Вывод:**
Текущий код имеет серьёзные ошибки, связанные с приоритетом операций, обработкой скобок и
переменными. Для корректной работы программы необходимо:
1. Реализовать вычисление с приоритетом операций.
2. Исправить функцию `change` для корректного раскрытия скобок.
3. Устранить ошибки в переменных и регистре.
Если потребуется, я могу предоставить полный рабочий пример на Pascal с реализацией
вычисления арифметических выражений.
_____________
матфак вгу и остальная классика =)