constk

LR14_Stack_RPN_Var_2 for Nikita

Sep 16th, 2020 (edited)
148
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include <iostream>
  2. #include "conio.h"
  3. #include <string>
  4. #include "Windows.h"
  5.  
  6. using namespace std;
  7.  
  8. struct Node // Узел списка
  9. {
  10.     double inf;
  11.     Node* next;
  12. };
  13.  
  14. class Stack // Класс для стека
  15. {
  16. public:
  17.     // Конструктор
  18.     Stack()
  19.     {
  20.         head = NULL; // Инициализируем вершину стека
  21.     }
  22.  
  23.     // Деструктор
  24.     ~Stack()
  25.     {
  26.         if (head == NULL) // Если стек пуст
  27.             return;
  28.  
  29.         while (head != NULL) // Пока не конец стека
  30.         {
  31.             Node* tPtr = head; // Запоминаем вершину стека чтобы удалить её позже
  32.             head = head->next; // Перемещаем указатель на вершину стека на следующий элемент
  33.             delete tPtr; // Удаляем предыдущую вершину стека
  34.         }
  35.     }
  36.  
  37.      // Поместить в стек число
  38.     void push(double x)
  39.     {
  40.         Node* newNode = new Node; // Создаём указатель под новый узел и выделяем по нему память
  41.         newNode->next = head; // Запоминаем адрес следующего элемента стека
  42.         newNode->inf = x; // Записываем число
  43.         head = newNode; // Перемещаем указатель на вершину стека на текущий узел
  44.     }
  45.  
  46.     // Извлечь число из стека и записать его по ссылке
  47.     int pop(double& x)
  48.     {
  49.         if (head == NULL) // Если стек пуст
  50.             return 1;
  51.  
  52.         x = head->inf; // Запоминаем число на верщине стека
  53.         Node* tPtr = head; // Запоминаем вершину стека чтобы удалить её позже
  54.         head = head->next; // Перемещаем указатель на вершину стека на следующий элемент
  55.         delete tPtr; // Удаляем предыдущую вершину стека
  56.         return 0; // Возвращает 0 если данные успешно извлечены
  57.     }
  58.  
  59.     // Пуст ли стек
  60.     bool isEmpty()
  61.     {
  62.         if (head == NULL) // Если стек пуст
  63.             return true; // Возвращаем 1
  64.         else // Иначе
  65.             return false; // Возвращаем 0
  66.     }
  67.  
  68. private:
  69.     Node* head; // Указатель на список
  70. };
  71.  
  72. int main()
  73. {
  74.     SetConsoleCP(1251);
  75.     SetConsoleOutputCP(1251);
  76.  
  77.     Stack * stack = new Stack();
  78.     string input;
  79.  
  80.     // Ввод выражения пользователем
  81.     cout << "Введите выражение в формате обратной польской нотации. Разделитель - пробел." << endl;
  82.     getline(cin, input);
  83.     const int N = input.length(); // Получаем длину введённой строки
  84.  
  85.     int newOperand = 0; // Новый операнд
  86.     double leftOperand = 0; // Левый операнд
  87.     double rightOperand = 0; // Правый операнд
  88.     char operation = 0; // Операция
  89.     double result = 0; // Переменная для записи результата
  90.  
  91.     bool allowPush = false; // Разрешена ли запись в стек
  92.     // Запись будет разрешена для чисел
  93.  
  94.     if (input.empty()) // Если пользователь ввёлл пустую строку
  95.     {
  96.         cerr << "#Ошибка! Введена пустая строка!" << endl;
  97.         system("pause>nul");
  98.         exit(1);
  99.     }      
  100.  
  101.     for (int i = 0; i < N; ++i) // Посимвольно обрабатываем введённую строку
  102.     {
  103.         if ((input.at(i) - 48) <= 9 && (input.at(i) - 48) >= 0) // Если встречена цифра
  104.         {
  105.             if (i >= N - 1) // Если эта цифра в конце выражения
  106.             {
  107.                 cerr << "#Ошибка! В данном формате число не должно стоять в конце!" << endl;
  108.                 system("pause>nul");
  109.                 exit(1);
  110.             }
  111.  
  112.             // Число умножаем на 10
  113.             // Записываем эту цифру в 0 разряд числа
  114.             newOperand *= 10;
  115.             newOperand += input.at(i) - 48;
  116.  
  117.             // Разрешаем запись в стек
  118.             allowPush = true;
  119.         }
  120.         else if (input.at(i) == ' ') // Если встречен разделитель (пробел)
  121.         {
  122.             if (allowPush == true) // Если разрешена запись в стек
  123.             {
  124.                 stack->push(newOperand); // Записываем число
  125.                 newOperand = 0; // Обнуляем переменную, содержащую число
  126.             }
  127.                
  128.             // Запрещаем запись
  129.             allowPush = false;
  130.         }
  131.         else if (input.at(i) == '+' || input.at(i) == '-' || input.at(i) == '*' || input.at(i) == '/') // Если встречена арифметическая операция
  132.         {
  133.             if (stack->pop(rightOperand) == 1 || stack->pop(leftOperand) == 1) // Если не можем извлечь числа из стека
  134.             {
  135.                 cerr << "#Ошибка! Нет чисел, над которыми можно провести операцию!" << endl;
  136.                 system("pause>nul");
  137.                 exit(1);
  138.             }
  139.  
  140.             // Выбираем операцию и записываем в стек результат
  141.             switch (input.at(i))
  142.             {
  143.             case '+': stack->push(leftOperand + rightOperand); break; // Сложение
  144.             case '-': stack->push(leftOperand - rightOperand); break; // Вычитание
  145.             case '*': stack->push(leftOperand * rightOperand); break; // Умножение
  146.             case '/': if (rightOperand != 0) stack->push(leftOperand / rightOperand); // Для деления выводим сообщение при делении на 0
  147.                       else { cerr << "#Ошибка! Нельзя делить на 0!" << endl; system("pause"); exit(0); } // и завершаем программу
  148.             }
  149.         }
  150.         else // Если ни один из случаев не произошёл, т.е. символ это не цифра, не разделитель и не операция
  151.         {
  152.             cerr << "#Ошибка! Неизвестные символы! Используйте только цифры, знаки +,-,*,/ и пробел" << endl;
  153.             system("pause>nul");
  154.             exit(1);
  155.         }
  156.     }
  157.     // Извлекаем результат из стека
  158.     stack->pop(result);
  159.  
  160.     if (stack->isEmpty() == false) // Если осталось лишнее число
  161.     {
  162.         cerr << "#Ошибка! Остались лишние числа!" << endl;
  163.         system("pause>nul");
  164.         exit(1);
  165.     }  
  166.    
  167.     cout << result << endl; // Выводим ответ
  168.  
  169.     system("pause");
  170.     return 0;
  171. }
RAW Paste Data