Написать программу формирования ОПЗ и расчета полученного выражения - Pascal ABC
Формулировка задачи:
Написать программу формирования ОПЗ и расчета полученного выражения. Разработать удобный интерфейс ввода исходных данных и вывода результатов. Работу программы проверить на конкретном примере
Сам пример со значениями которые должны получиться: (a– b)/(c+d)*e , где а=0.3 b=6.7 c=8.4 d=9.6 e=1.2 Результат должен получиться -0.429. Помогите пожалуйста используя динамический массив заранее спасибо
Решение задачи: «Написать программу формирования ОПЗ и расчета полученного выражения»
textual
Листинг программы
- uses math;
- type arr = array of string[20];
- //процедура помещения токена в стек
- procedure push(var x: arr; var y: string);
- begin
- setlength(x, length(x) + 1); //увеличиваем глубину стека
- x[high(x)] := y //помещаем токен
- end;
- //процедура извлечения токена из стека
- procedure pop(var x: arr; var y: string);
- begin
- y := x[high(x)]; //извлекаем токен
- setlength(x, length(x) - 1) //уменьшаем глубину стека
- end;
- const op = '()+-*/^'; //операторы в порядке возрастания приоритетов
- var s, t, q, error: string; //входная строка, буферы токена, сообщение об ошибке
- i, err: integer; //счётчик, ошибка преобразования строки в число
- num: real; //проверочный результат
- st, st_op: arr; //выходной стек, стек операций
- st_n: array of real; //стек операндов
- begin
- writeln('Введите выражение:'); //ввод выражения в инфиксной нотации
- readln(s);
- s := s + ' '; //добавляем пробел для удобства алгоритма
- for i := length(s) downto 1 do //разбиваем пробелами выражение на токены
- if pos(s[i], op) > 0 //если очередной символ - оператор
- then begin //то вставляем пробелы до и после него
- insert(' ', s, i + 1);
- insert(' ', s, i)
- end;
- while pos(' ', s) > 0 do delete(s, pos(' ', s), 1); //убираем лишние пробелы
- if (length(s) > 0) and (s[1] = ' ') then delete(s, 1, 1);
- if length(s) = 0 //если строка пустая
- then error := 'Ошибка: пустое выражение' //формируем сообщение об ошибке и более ничего не делаем
- else begin //если строка не пустая, то
- writeln('Выражение:'); //печатаем выражение, разбитое на токены
- writeln(s);
- t := ''; //инициализируем буфер токена: пока пустой
- for i := 1 to length(s) do //сканируем выражение
- begin
- if s[i] <> ' ' //если не пробел,
- then t := t + s[i] //то помещаем символ в буфер токена
- else begin //иначе разбираемся с токеном
- case t[1] of //смотрим первый символ токена
- '0'..'9', '.': //если относится к числу,
- begin //то
- val(t, num, err); //проверяем, является ли токен допустимой записью числа
- if err = 0
- then push(st, t) //если да, то помещаем токен в выходной стек
- else begin //если нет,
- error := 'Ошибка: не число: ' + t; //то формируем текст ошибки
- break //и прекращаем сканирование
- end
- end;
- '(': //если открывающая скобка,
- push(st_op, t); //то помещаем токен в стек
- ')':
- begin //если закрывающая скобка,
- while (length(st_op) > 0) and (t[1] <> '(') do //то пока не встретился токен '(' и стек операторов не опустел
- begin
- pop(st_op, t); //извлекаем токен из стека операторов
- if t[1] <> '(' then push(st, t) //и помещаем его в выходной стек
- end;
- if t[1] <> '(' //если последний извлечённый токен не '(',
- then begin
- error := 'Ошибка: нарушен баланс скобок'; //то формируем текст ошибки
- break //и прекращаем сканирование
- end
- end;
- '+', '-', '*', '/', '^': //если токен - операция,
- begin
- //то пока стек операторов не пустой и операция на вершине стека операторов с большим или равным приоритетом,
- while (length(st_op) > 0) and ((pos(t[1], op) - 1) div 2 <= (pos(st_op[high(st_op)][1], op) - 1) div 2) do
- begin
- pop(st_op, q); //извлекаем токен из стека операторов
- push(st, q); //помещаем токен в выходной стек
- end;
- push(st_op, t); //добавляем токен к стеку операторов
- end
- else //если токен какой-то другой,
- begin
- error := 'Ошибка: недействительный оператор: ' + t; //то формируем текст ошибки
- break //и прекращаем сканирование
- end
- end;
- t := '' //реинициализируем буфер токена
- end;
- end;
- //сканирование окончено
- while length(st_op) > 0 do //если в стеке операторов остались операторы, перемещаем их в выходной стек
- if pos(st_op[high(st_op)][1], op) < 3 //если оператор - скобка,
- then begin
- error := 'Ошибка: нарушен баланс скобок'; //то формируем текст ошибки
- break //и прекращаем перемещение
- end
- else begin //если оператор - не скобка,
- pop(st_op, t); //то извлекаем его из стека операторов
- push(st, t) //и помещаем в выходной стек
- end;
- end;
- if (length(st) > 0) and (length(error) = 0) //если выходной стек не пуст и нет ошибки,
- then begin //то
- writeln('ОПЗ:'); //печатаем выражение в постфиксной нотации
- for i := 0 to high(st) do write(st[i], ' ');
- writeln;
- for i := 0 to high(st) do //пробегаемся по выходному стеку и пытаемся вычислить выражение
- case st[i][1] of
- '+', '-', '*', '/', '^': //если токен - оператор,
- begin //то пытаемся выполнить операцию
- case st[i][1] of //смотрим, что за оператор
- '+': st_n[high(st_n) - 1] := st_n[high(st_n) - 1] + st_n[high(st_n)]; //находим сумму
- '-': st_n[high(st_n) - 1] := st_n[high(st_n) - 1] - st_n[high(st_n)]; //находим разность
- '*': st_n[high(st_n) - 1] := st_n[high(st_n) - 1] * st_n[high(st_n)]; //находим произведение
- '/': //деление
- if st_n[high(st_n)] <> 0 //если делитель не равен 0
- then st_n[high(st_n) - 1] := st_n[high(st_n) - 1] / st_n[high(st_n)] //то находим частное
- else begin //иначе ошибка деления на 0
- error := 'Ошибка: деление на ноль';
- break
- end;
- '^': //возведение в степень
- if (st_n[high(st_n) - 1] = 0) and (st_n[high(st_n)] = 0) //если 0^0
- then begin //то ошибка 0^0
- error := 'Ошибка: 0^0';
- break
- end
- else if (frac(1 / st_n[high(st_n)]) = 0) and not odd(trunc(1 / st_n[high(st_n)])) and (st_n[high(st_n) - 1] < 0)
- then begin //если корень чётной степени из отрицательного числа, то ошибка
- error := 'Ошибка: корень чётной степени из отрицательного числа';
- break
- end
- else if st_n[high(st_n) - 1] > 0 //если всё в норме, вычисляем степень
- then st_n[high(st_n) - 1] := exp(ln(st_n[high(st_n) - 1]) * st_n[high(st_n)])
- else if st_n[high(st_n) - 1] < 0
- then st_n[high(st_n) - 1] := -exp(ln(-st_n[high(st_n) - 1]) * st_n[high(st_n)])
- else st_n[high(st_n) - 1] := 0
- end;
- setlength(st_n, length(st_n) - 1) //операция выполнена, убираем второй операнд из стека (результат помещён на место первого операнда)
- end
- else begin //если не оператор,
- setlength(st_n, length(st_n) + 1); //то увеличиваем глубину стека операндов
- val(st[i], st_n[high(st_n)], err) //и помещаем в стек операндов токен, преобразованный в число
- end
- end
- end;
- if length(error) > 0 //если есть ошибка,
- then write(error) //то печатаем её
- else write('Результат: ', st_n[high(st_n)]:0:15); //иначе печатаем результат
- readln
- end.
Объяснение кода листинга программы
Этот код написан на языке Pascal ABC и предназначен для формирования ОПЗ (обратного порядка слов) и расчета выражений, введенных пользователем. Он работает следующим образом:
- Пользователь вводит выражение, которое затем разбивается на отдельные токены.
- Каждый токен проверяется на соответствие определенным правилам языка.
- Если токен является оператором, то он помещается в стек операторов.
- Если токен является числом, то он преобразуется в число и помещается в стек чисел.
- Выполняются операции в стеке операторов до тех пор, пока не закончатся операторы или все числа будут использованы.
- Результат вычислений помещается в стек чисел.
- Стеки чисел и операторов очищаются.
- Выводится результат вычислений. Код содержит несколько проверок на ошибки, таких как деление на ноль, ошибка баланса скобок и другие. Если происходит ошибка, то выводится соответствующее сообщение об ошибке. Этот код может быть использован для решения различных задач, связанных с вычислением выражений на языке Pascal.
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д