Написать программу формирования ОПЗ и расчета полученного выражения - Pascal ABC

Узнай цену своей работы

Формулировка задачи:

Написать программу формирования ОПЗ и расчета полученного выражения. Разработать удобный интерфейс ввода исходных данных и вывода результатов. Работу программы проверить на конкретном примере Сам пример со значениями которые должны получиться: (a– b)/(c+d)*e , где а=0.3 b=6.7 c=8.4 d=9.6 e=1.2 Результат должен получиться -0.429. Помогите пожалуйста используя динамический массив заранее спасибо

Решение задачи: «Написать программу формирования ОПЗ и расчета полученного выражения»

textual
Листинг программы
  1. uses math;
  2. type arr = array of string[20];
  3.  
  4. //процедура помещения токена в стек
  5. procedure push(var x: arr; var y: string);
  6. begin
  7.   setlength(x, length(x) + 1); //увеличиваем глубину стека
  8.   x[high(x)] := y //помещаем токен
  9. end;
  10.  
  11. //процедура извлечения токена из стека
  12. procedure pop(var x: arr; var y: string);
  13. begin
  14.   y := x[high(x)]; //извлекаем токен
  15.   setlength(x, length(x) - 1) //уменьшаем глубину стека
  16. end;
  17.  
  18. const op = '()+-*/^'; //операторы в порядке возрастания приоритетов
  19. var s, t, q, error: string; //входная строка, буферы токена, сообщение об ошибке
  20.     i, err: integer; //счётчик, ошибка преобразования строки в число
  21.     num: real; //проверочный результат
  22.     st, st_op: arr; //выходной стек, стек операций
  23.     st_n: array of real; //стек операндов
  24. begin
  25.   writeln('Введите выражение:'); //ввод выражения в инфиксной нотации
  26.   readln(s);
  27.   s := s + ' '; //добавляем пробел для удобства алгоритма
  28.   for i := length(s) downto 1 do //разбиваем пробелами выражение на токены
  29.     if pos(s[i], op) > 0 //если очередной символ - оператор
  30.       then begin //то вставляем пробелы до и после него
  31.         insert(' ', s, i + 1);
  32.         insert(' ', s, i)
  33.       end;
  34.   while pos('  ', s) > 0 do delete(s, pos('  ', s), 1); //убираем лишние пробелы
  35.   if (length(s) > 0) and (s[1] = ' ') then delete(s, 1, 1);
  36.   if length(s) = 0 //если строка пустая
  37.     then error := 'Ошибка: пустое выражение' //формируем сообщение об ошибке и более ничего не делаем
  38.     else begin //если строка не пустая, то
  39.       writeln('Выражение:'); //печатаем выражение, разбитое на токены
  40.       writeln(s);
  41.       t := ''; //инициализируем буфер токена: пока пустой
  42.       for i := 1 to length(s) do //сканируем выражение
  43.         begin
  44.           if s[i] <> ' ' //если не пробел,
  45.             then t := t + s[i] //то помещаем символ в буфер токена
  46.             else begin //иначе разбираемся с токеном
  47.               case t[1] of //смотрим первый символ токена
  48.                   '0'..'9', '.': //если относится к числу,
  49.                     begin //то
  50.                       val(t, num, err); //проверяем, является ли токен допустимой записью числа
  51.                       if err = 0
  52.                         then push(st, t) //если да, то помещаем токен в выходной стек
  53.                         else begin //если нет,
  54.                           error := 'Ошибка: не число: ' + t; //то формируем текст ошибки
  55.                           break //и прекращаем сканирование
  56.                         end
  57.                     end;
  58.                   '(': //если открывающая скобка,
  59.                     push(st_op, t); //то помещаем токен в стек
  60.                   ')':
  61.                     begin //если закрывающая скобка,
  62.                       while (length(st_op) > 0) and (t[1] <> '(') do //то пока не встретился токен '(' и стек операторов не опустел
  63.                         begin
  64.                           pop(st_op, t); //извлекаем токен из стека операторов
  65.                           if t[1] <> '(' then push(st, t) //и помещаем его в выходной стек
  66.                         end;
  67.                       if t[1] <> '(' //если последний извлечённый токен не '(',
  68.                         then begin
  69.                           error := 'Ошибка: нарушен баланс скобок'; //то формируем текст ошибки
  70.                           break //и прекращаем сканирование
  71.                         end
  72.                     end;
  73.                   '+', '-', '*', '/', '^': //если токен - операция,
  74.                     begin
  75.                       //то пока стек операторов не пустой и операция на вершине стека операторов с большим или равным приоритетом,
  76.                       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
  77.                         begin
  78.                           pop(st_op, q); //извлекаем токен из стека операторов
  79.                           push(st, q); //помещаем токен в выходной стек
  80.                         end;
  81.                       push(st_op, t); //добавляем токен к стеку операторов
  82.                     end
  83.                   else //если токен какой-то другой,
  84.                     begin
  85.                       error := 'Ошибка: недействительный оператор: ' + t; //то формируем текст ошибки
  86.                       break //и прекращаем сканирование
  87.                     end
  88.                 end;
  89.               t := '' //реинициализируем буфер токена
  90.             end;
  91.         end;
  92.         //сканирование окончено
  93.       while length(st_op) > 0 do //если в стеке операторов остались операторы, перемещаем их в выходной стек
  94.         if pos(st_op[high(st_op)][1], op) < 3 //если оператор - скобка,
  95.           then begin
  96.             error := 'Ошибка: нарушен баланс скобок'; //то формируем текст ошибки
  97.             break //и прекращаем перемещение
  98.           end
  99.           else begin //если оператор - не скобка,
  100.             pop(st_op, t); //то извлекаем его из стека операторов
  101.             push(st, t) //и помещаем в выходной стек
  102.           end;
  103.     end;
  104.   if (length(st) > 0) and (length(error) = 0) //если выходной стек не пуст и нет ошибки,
  105.     then begin //то
  106.       writeln('ОПЗ:'); //печатаем выражение в постфиксной нотации
  107.       for i := 0 to high(st) do write(st[i], ' ');
  108.       writeln;
  109.       for i := 0 to high(st) do //пробегаемся по выходному стеку и пытаемся вычислить выражение
  110.         case st[i][1] of
  111.             '+', '-', '*', '/', '^': //если токен - оператор,
  112.               begin //то пытаемся выполнить операцию
  113.                 case st[i][1] of //смотрим, что за оператор
  114.                     '+': st_n[high(st_n) - 1] := st_n[high(st_n) - 1] + st_n[high(st_n)]; //находим сумму
  115.                     '-': st_n[high(st_n) - 1] := st_n[high(st_n) - 1] - st_n[high(st_n)]; //находим разность
  116.                     '*': st_n[high(st_n) - 1] := st_n[high(st_n) - 1] * st_n[high(st_n)]; //находим произведение
  117.                     '/': //деление
  118.                       if st_n[high(st_n)] <> 0 //если делитель не равен 0
  119.                         then st_n[high(st_n) - 1] := st_n[high(st_n) - 1] / st_n[high(st_n)] //то находим частное
  120.                         else begin //иначе ошибка деления на 0
  121.                           error := 'Ошибка: деление на ноль';
  122.                           break
  123.                         end;
  124.                     '^': //возведение в степень
  125.                       if (st_n[high(st_n) - 1] = 0) and (st_n[high(st_n)] = 0) //если 0^0
  126.                         then begin //то ошибка 0^0
  127.                           error := 'Ошибка: 0^0';
  128.                           break
  129.                         end
  130.                         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)
  131.                           then begin //если корень чётной степени из отрицательного числа, то ошибка
  132.                             error := 'Ошибка: корень чётной степени из отрицательного числа';
  133.                             break
  134.                           end
  135.                           else if st_n[high(st_n) - 1] > 0 //если всё в норме, вычисляем степень
  136.                             then st_n[high(st_n) - 1] := exp(ln(st_n[high(st_n) - 1]) * st_n[high(st_n)])
  137.                             else if st_n[high(st_n) - 1] < 0
  138.                               then st_n[high(st_n) - 1] := -exp(ln(-st_n[high(st_n) - 1]) * st_n[high(st_n)])
  139.                               else st_n[high(st_n) - 1] := 0
  140.                   end;
  141.                 setlength(st_n, length(st_n) - 1) //операция выполнена, убираем второй операнд из стека (результат помещён на место первого операнда)
  142.               end
  143.             else begin //если не оператор,
  144.               setlength(st_n, length(st_n) + 1); //то увеличиваем глубину стека операндов
  145.               val(st[i], st_n[high(st_n)], err) //и помещаем в стек операндов токен, преобразованный в число
  146.             end
  147.           end
  148.     end;
  149.   if length(error) > 0 //если есть ошибка,
  150.     then write(error) //то печатаем её
  151.     else write('Результат: ', st_n[high(st_n)]:0:15); //иначе печатаем результат
  152.   readln
  153. end.

Объяснение кода листинга программы

Этот код написан на языке Pascal ABC и предназначен для формирования ОПЗ (обратного порядка слов) и расчета выражений, введенных пользователем. Он работает следующим образом:

  1. Пользователь вводит выражение, которое затем разбивается на отдельные токены.
  2. Каждый токен проверяется на соответствие определенным правилам языка.
  3. Если токен является оператором, то он помещается в стек операторов.
  4. Если токен является числом, то он преобразуется в число и помещается в стек чисел.
  5. Выполняются операции в стеке операторов до тех пор, пока не закончатся операторы или все числа будут использованы.
  6. Результат вычислений помещается в стек чисел.
  7. Стеки чисел и операторов очищаются.
  8. Выводится результат вычислений. Код содержит несколько проверок на ошибки, таких как деление на ноль, ошибка баланса скобок и другие. Если происходит ошибка, то выводится соответствующее сообщение об ошибке. Этот код может быть использован для решения различных задач, связанных с вычислением выражений на языке Pascal.

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

11   голосов , оценка 3.545 из 5

Нужна аналогичная работа?

Оформи быстрый заказ и узнай стоимость

Бесплатно
Оформите заказ и авторы начнут откликаться уже через 10 минут
Похожие ответы