Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include "conio.h"
- #include <string>
- #include "Windows.h"
- using namespace std;
- struct Node // Узел списка
- {
- double inf;
- Node* next;
- };
- class Stack // Класс для стека
- {
- public:
- // Конструктор
- Stack()
- {
- head = NULL; // Инициализируем вершину стека
- }
- // Деструктор
- ~Stack()
- {
- if (head == NULL) // Если стек пуст
- return;
- while (head != NULL) // Пока не конец стека
- {
- Node* tPtr = head; // Запоминаем вершину стека чтобы удалить её позже
- head = head->next; // Перемещаем указатель на вершину стека на следующий элемент
- delete tPtr; // Удаляем предыдущую вершину стека
- }
- }
- // Поместить в стек число
- void push(double x)
- {
- Node* newNode = new Node; // Создаём указатель под новый узел и выделяем по нему память
- newNode->next = head; // Запоминаем адрес следующего элемента стека
- newNode->inf = x; // Записываем число
- head = newNode; // Перемещаем указатель на вершину стека на текущий узел
- }
- // Извлечь число из стека и записать его по ссылке
- int pop(double& x)
- {
- if (head == NULL) // Если стек пуст
- return 1;
- x = head->inf; // Запоминаем число на верщине стека
- Node* tPtr = head; // Запоминаем вершину стека чтобы удалить её позже
- head = head->next; // Перемещаем указатель на вершину стека на следующий элемент
- delete tPtr; // Удаляем предыдущую вершину стека
- return 0; // Возвращает 0 если данные успешно извлечены
- }
- // Пуст ли стек
- bool isEmpty()
- {
- if (head == NULL) // Если стек пуст
- return true; // Возвращаем 1
- else // Иначе
- return false; // Возвращаем 0
- }
- private:
- Node* head; // Указатель на список
- };
- int main()
- {
- SetConsoleCP(1251);
- SetConsoleOutputCP(1251);
- Stack * stack = new Stack();
- string input;
- // Ввод выражения пользователем
- cout << "Введите выражение в формате обратной польской нотации. Разделитель - пробел." << endl;
- getline(cin, input);
- const int N = input.length(); // Получаем длину введённой строки
- int newOperand = 0; // Новый операнд
- double leftOperand = 0; // Левый операнд
- double rightOperand = 0; // Правый операнд
- char operation = 0; // Операция
- double result = 0; // Переменная для записи результата
- bool allowPush = false; // Разрешена ли запись в стек
- // Запись будет разрешена для чисел
- if (input.empty()) // Если пользователь ввёлл пустую строку
- {
- cerr << "#Ошибка! Введена пустая строка!" << endl;
- system("pause>nul");
- exit(1);
- }
- for (int i = 0; i < N; ++i) // Посимвольно обрабатываем введённую строку
- {
- if ((input.at(i) - 48) <= 9 && (input.at(i) - 48) >= 0) // Если встречена цифра
- {
- if (i >= N - 1) // Если эта цифра в конце выражения
- {
- cerr << "#Ошибка! В данном формате число не должно стоять в конце!" << endl;
- system("pause>nul");
- exit(1);
- }
- // Число умножаем на 10
- // Записываем эту цифру в 0 разряд числа
- newOperand *= 10;
- newOperand += input.at(i) - 48;
- // Разрешаем запись в стек
- allowPush = true;
- }
- else if (input.at(i) == ' ') // Если встречен разделитель (пробел)
- {
- if (allowPush == true) // Если разрешена запись в стек
- {
- stack->push(newOperand); // Записываем число
- newOperand = 0; // Обнуляем переменную, содержащую число
- }
- // Запрещаем запись
- allowPush = false;
- }
- else if (input.at(i) == '+' || input.at(i) == '-' || input.at(i) == '*' || input.at(i) == '/') // Если встречена арифметическая операция
- {
- if (stack->pop(rightOperand) == 1 || stack->pop(leftOperand) == 1) // Если не можем извлечь числа из стека
- {
- cerr << "#Ошибка! Нет чисел, над которыми можно провести операцию!" << endl;
- system("pause>nul");
- exit(1);
- }
- // Выбираем операцию и записываем в стек результат
- switch (input.at(i))
- {
- case '+': stack->push(leftOperand + rightOperand); break; // Сложение
- case '-': stack->push(leftOperand - rightOperand); break; // Вычитание
- case '*': stack->push(leftOperand * rightOperand); break; // Умножение
- case '/': if (rightOperand != 0) stack->push(leftOperand / rightOperand); // Для деления выводим сообщение при делении на 0
- else { cerr << "#Ошибка! Нельзя делить на 0!" << endl; system("pause"); exit(0); } // и завершаем программу
- }
- }
- else // Если ни один из случаев не произошёл, т.е. символ это не цифра, не разделитель и не операция
- {
- cerr << "#Ошибка! Неизвестные символы! Используйте только цифры, знаки +,-,*,/ и пробел" << endl;
- system("pause>nul");
- exit(1);
- }
- }
- // Извлекаем результат из стека
- stack->pop(result);
- if (stack->isEmpty() == false) // Если осталось лишнее число
- {
- cerr << "#Ошибка! Остались лишние числа!" << endl;
- system("pause>nul");
- exit(1);
- }
- cout << result << endl; // Выводим ответ
- system("pause");
- return 0;
- }
Add Comment
Please, Sign In to add comment