Написать программу формирования ОПЗ и расчета полученного выражения - 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.
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д