"Польский" калькулятор
Внимание! Это довольно старый топик, посты в него не попадут в новые, и их никто не увидит. Пишите пост, если хотите просто дополнить топик, а чтобы задать новый вопрос — начните новый.
Внимание! Это довольно старый топик, посты в него не попадут в новые, и их никто не увидит. Пишите пост, если хотите просто дополнить топик, а чтобы задать новый вопрос — начните новый.
Помогите с заданием. Не знаю с какого боку подступиться :(
Написать консольную программу, реализующую калькулятор с использованием обратной польской нотации. Количество операндов в выражении не более 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);
}
}
Все заколебался писать, будут вопросы спрашивай.
Только так.
Или я не так Вас понимаю?