"Польский" калькулятор

"Польский" калькулятор

Помогите с заданием. Не знаю с какого боку подступиться :(

Написать консольную программу, реализующую калькулятор с использованием обратной польской нотации. Количество операндов в выражении не более 100. Сделать обработку ошибочных ситуаций.

Обычный калькулятор (типа введите первое число, введите знак, введите второе число) у меня получается без проблем. Но здесь количество чисел неизвестно. Да еще и польская нотация. В общем help!

Спасибо, но теоретически это я в общем знаю. Мне непонятно как программу сделать. Вапще непонятно :( Даже как данные вводить. Там же может быть и число и знак операции. Если бы было всегда число, число, операция, то это был бы калькулятор который я уже сделал. Только порядок ввода переменных переставить надо. А как стек для этого калькулятора сделать? А еще как обработку ошибок сделать? Одни вопросы. Моск плавицца :(

Держи разбирайся. Ввод записи типа: ((((2+3)/5+85)-1)2.5-90)^2. Сделано через стек; работает с вещественными числами, символы /*-+^() обрабатывает по созданным в программе приоритетам, в общем разберешься. Написана в Qt.

Спасибо, Евгений! Только это для меня очень сложно. Я посмотрел вашу программу и половину вообще не понял :( У меня с классами пока сложности (надеюсь временные).
И ваша программа делает больше, чем надо мне. Как я понял она принимает выражение в инфиксной форме, переводит в обратную польскую, а затем вычисляет. А мне надо просто вычислить выражение, которое уже задано в обратной польской нотации.
Но все равно спасибо. Буду пробовать разобраться и выделить нужный мне кусок.

Немного помогу разобраться.
Начнем с собственного типа данных:
Итак. Ты допустим имеешь постфиксную запись: 23+, что в инфиксной форме выглядит как 2+3. Что нам нужно для работы с любой записью это разбить ее на элементы и записать в массив, в моем случае это массив структур DAC, почему массив структур, потому что числа могут быть отрицательными, а минус это символ и поэтому для проверки мы создаем доп. переменную isDouble, которая указывает нам чем является элемент структуры DAC числом или символом.
struct DAC
{
double x; //Непосредственно само вещественное число
char operation; //Символ операции +-*/^
bool isDouble; //Необходим для проверки является ли элемент массива числом или знаком
};
В остальном polishstack.cpp и polishstack.h это стандартный стек, который может быть реализован не через класс, а любым удобным для тебя способом. Основная программа находится в main.
Начну с конца а это обработчик исключений (ошибок)
try
{
...
}
catch (exception &e)
{
cerr << e.what() << endl;
} //Нужно для того, чтобы не писать обработчики для всех возможных ошибок, которые могут возникнуть из-за неправильного ввода, а просто вывести, что-то типа неизвестная ошибка.

По нюансам:
previousWasNumber — Переменная необходимая для определения отрицательного числа в записи, если перед минусом шло число, значит это символ -, если перед минусом шел другой символ -+*/^, то это отрицательное число.

Немного по стеку, стек можно представить ка стопку тарелок, т.е. это такая упорядоченная структура данных, с которой организованна работа по принципу последней положил, первой забрал. В программе — push — ложить, pop — забирать, onTop — верхняя тарелка, isEmpty — а есть ли еще тарелки?. Алгоритм в двух словах:
Заносишь в массив свою запись поэлементно, запись постфиксная- 234+-2, инфиксная — 2+34+(-2), записываем поэлементно ее в массив 2 + 3 * 4 + — ( 2 ), массив получился из 10 символов, скобки нужны для разруливания приоритетов, и в постфиксный массив они не записываются. Итак стек мы будем использовать два раза, для формирования постфиксной записи из инфиксной и расчета полученной постфиксной, в принципе как и сам массив. Для обработки приоритетов была написана простенькая функция int priority(DAC symbol), которая возращает число в зависимости от заданного нами приоритета для символа в ней. Затем эти приоритеты сравниваются и происходит запись в стек нашего массива в постфиксной форме. После того как массив записан в стек полностью в постфиксной форме, сливаем его в новый polishArray[i].
Затем загоняем получившейся массив и сопоставляем символы реальным операциям +-/^ таким способом:
for (unsigned int i = 0; i < j; i++)
{
if (polishArray[i].isDouble)
{
stack.push(polishArray[i]);
}
else
{
double resultDouble;
DAC secondNumber = stack.onTop();
stack.pop();
DAC firstNumber = stack.onTop();
stack.pop();
if (polishArray[i].operation == '+')
{
resultDouble = firstNumber.x + secondNumber.x;
}
if (polishArray[i].operation == '-')
{
resultDouble = firstNumber.x — secondNumber.x;
}
if (polishArray[i].operation == '
')
{
resultDouble = firstNumber.x * secondNumber.x;
}
if (polishArray[i].operation == '/')
{
resultDouble = firstNumber.x / secondNumber.x;
}
if (polishArray[i].operation == '^')
{
resultDouble = pow(firstNumber.x, secondNumber.x);
}
DAC result = { resultDouble, 'H', true };
stack.push(result);
}
}
Все заколебался писать, будут вопросы спрашивай.

А мне надо просто вычислить выражение, которое уже задано в обратной польской нотации.
Вопрос только в том как вы собираетесь разграничивать числа между собой для выражения в польской нотации.
Пример польской нотации заданной строкой а не массивом:
1234+
Что я написал:
12+34?
1+234?
123+4?
В вашем случае можно только выделить массив на N-ое количество элементов и вводить символы.
Пример:
Заполните массив в постфиксной форме. Для завершения ввода нажмите пробел.
Введите 1 элемент:
12
Введите 2 элемент:
34
Введите 3 элемент:
+
Введите 4 элемент:
Пробел
Ответ: 46

Только так.
Или я не так Вас понимаю?

Внимание! Это довольно старый топик, посты в него не попадут в новые, и их никто не увидит. Пишите пост, если хотите просто дополнить топик, а чтобы задать новый вопрос — начните новый.

Ответить

Вы можете использовать разметку markdown для оформления комментариев и постов. Используйте функцию предпросмотра для проверки корректности разметки.

Пожалуйста, оформляйте исходный код в соответствии с правилами разметки. Для того, чтобы вставить код в комментарий, скопируйте его в текстовое поле ниже, после чего выделите то, что скопировали и нажмите кнопку «код» в панели инструментов. Иначе ваш код может принять нечитаемый вид.

Либо производите оформление кода вручную, следующим образом:

``` #include <iostream> using namespace std; int main() { // ... } ```

Предпросмотр сообщения

Ваше сообщение пусто.