Язык Си в примерах/Калькулятор выражений в обратной польской нотации: различия между версиями
Содержимое удалено Содержимое добавлено
Нет описания правки |
ISbot (обсуждение | вклад) м Замена <tt /> на <code />; избыточные <big /> и <font /> вокруг <source />; {{SUBPAGENAME}}; пробелы. |
||
Строка 3:
==Что такое обратная польская нотация?==
Рассмотрим запись арифметических выражений, в которых сначала следуют два операнда арифметической
операции, а затем знак операции. Например:
Строка 10:
|'''Обычная нотация'''
|-
|2 3 +
|2 + 3
|-
|2 3 * 4 5 * +
|(2 * 3) + (4 * 5)
|-
|2 3 4 5 6 * + - /
|2 / (3 - (4 + (5 * 6)))
|}
Это нотация записи выражений называется [[w:Обратная польская нотация|обратной польской нотацией (записью)]] (Reverse Polish Notation, RPN).
В теории языков программирования эта нотация называется ''постфиксной нотацией''. Обычная нотация называется алгебраической или ''инфиксной нотацией''
(«ин» от англ. ''inside'', то есть между операндами). Есть также префиксная нотация, активно используемая в языке Си (сначала имя функции, а затем её аргументы), а также в языке [[:w:LISP|LISP]].
Заметьте, что скобки в обратной польской нотации не нужны. В частности, если во втором примере мы
опустим скобки, выражение по прежнему будет интерпретироваться однозначно.
Транслятор RPN-выражений основан на [[w:Стек|стэке]]. Каждое следующее число
помещается в стэк. Если встречается знак операции (обозначим его <
'''Задача:''' Напишите программу-калькулятор арифметических выражений записанных в обратной польской нотации.
Ниже приведена простая реализация такого калькулятора на языке Си.
Роль стека играет обычный массив (stack[1000]). Переменная <
Число (<
#include <stdio.h>
int main()
Строка 79:
return 0;
}
</source
===Пример работы программы===
Строка 92:
===Задания===
# Введите входные следующие входные данные <
# Введите входные данные состоящие из 10000 единиц и 9999 знаков +. Сможет ли программа отработать на этих входных данных?
Строка 98:
===Замечания===
# У данной программы есть целый ряд недостатков:
:* Программа не будет работать, если количество элементов в стеке превысит 1000
:* Программа не замечает некорректные входы и отрабатывает их с непредсказуемыми последстиями.
:* В программе явно не отображено, что присутствует структура данных «стек». Это затрудняет понимание логики работы этой программы и усложняет сторонним разработчикам доработку данной программы.
Строка 107:
Введем операции работы со стеком в программу. Это повысит читаемость кода и облегчит понимание заложенной в программу логики.
#include <stdio.h>
#include <malloc.h>
Строка 160:
return 0;
}
</source
В данной программе в некоторой степени реализована «защита от дурака», а именно, если вводится выражение, в котором число операций превосходит число
помещенных в стек элементов (например <
=== Выделение стека в отдельную структуру ===
Кроме защиты от дурака-пользователя необходима еще защита от дурака-программиста, который возьмет ваш код, решит его использовать и дорабатывать.
Точнее, нужно просто соблюдать некоторые правила, которые не позволили бы программисту, который включил ваш код в свой проект получить ошибки,
связанные с пересечением имён, испольуемых им в своих файлах и вами, в файле <
В первую очередь, в принципе не рекомендуется объявлять глобальные переменные, особенно такие, которые не являются всеобщим достоянием, а относятся к внутренним делам отдельного модуля (например, нашей программы, для работы со стеком).
Кроме того, рекомендуется имена функций присутствующие в билиотеке снабжать префиксом.
Например, имена функций, связанных со стеком, логично снабдить префиксом <
В итоге получаем следующую, «более правильную» реализацию стека:
#include <malloc.h>
/* Структура с указателем на массив int и служебной информацией
Строка 229:
}
}
</source
===Задания===
Строка 235:
# Реализуйте RPN-калькулятор, используя эту реализацию стека. Выделите вычисление RPN-выражения в отдельную функцию.
# Постройте систему тестов и проверьте, что ваш калькулятор успешно проходит все тесты и «защищён от дурака» (как дурака-пользователя программы, так и дурака-программиста, использующего ваш стек и калькулятор).
[[Категория:Язык Си в примерах|
|