Проблема C ++ Reverse Poli sh Калькулятор нотации - PullRequest
0 голосов
/ 29 мая 2020

У меня проблема с РПН. Я хочу, чтобы программа завершила sh ввод символов после нажатия клавиши ENTER, но что-то не работает, потому что она не записывает в ve c. Пытался решить задачу: Значение записанного в Reverse Poli выражения sh Notation должно определяться. Выражение будет содержать следующие операторы: +, -, * и / (целочисленное деление) и натуральные числа не более одного миллиона. Результатом является тип int.

Entrance В первой и единственной строке фраза, записанная в Reverse Poli sh Notation. Операторы отделяются от чисел пробелом. Длина выражения меньше 1000 символов.

Exit Конечное значение выражения ONP.

#include <iostream>
#include <vector>
#include <stack>

using namespace std;

int RPN(vector<string> &notation) {
  stack<int> s;
  for (string str : notation) {
    if (str == "+" or str == "-" or str == "/" or str == "*") {
      int a = s.top();
      s.pop();
      int b = s.top();
      s.pop();

      if (str == "-") {
        s.push(b - a);
        continue;
      }
      if (str == "+") {
        s.push(b + a);
        continue;
      }
      if (str == "/") {
        s.push(b / a);
        continue;
      }
      if (str == "*") {
        s.push(b * a);
        continue;
      }
    } else
      s.push(stoi(str));
  }
  return s.top();
}

int main() {
  vector<string> notation;

  while (true) {
    string sign;
    cin >> sign;
    if (cin.get() != 'n') {
      break;
    } else {
      notation.push_back(sign);
    }
  }
  for (auto i : notation)  // test, print vec
  {
    cout << i << endl;
    ;
  }
  cout << RPN(notation) << endl;
return 0;
}

1 Ответ

0 голосов
/ 29 мая 2020

Ваш код не имеет приоритета. Он относится к сложению так же, как и к умножению. Если это то, что вы хотите, вы можете просто выполнять каждую операцию слева направо.

Полагаю, цель вашей программы - иметь некоторый приоритет и выполнять, например, умножение перед сложением.

Вот простой код, сохраняющий приоритет. Код предполагает, что ввод всегда правильный, и для простоты не обрабатываются круглые скобки.

#include <iostream>
#include <vector>
#include <stack>

int getPrecedence(std::string &o)
{
    if (o == "+" || o == "-")
        return 1;

    return 2;
}

int calculate(int a, int b, const std::string &operation)
{
    if (operation == "+")
        return a + b;
    if (operation == "-")
        return a - b;
    if (operation == "*")
        return a * b;
    if (operation == "/")
        return a / b;
    return -1;
}

void performOperation(std::stack<int> &numbers, std::stack<std::string> &operators) {
    int n1 = numbers.top();
    numbers.pop();
    int n2 = numbers.top();
    numbers.pop();
    std::string op = operators.top();
    operators.pop();

    numbers.push(calculate(n2, n1, op));
}

int RPN(std::vector<std::string> &notation) {

    std::stack<int> numbers;
    std::stack<std::string> operators;

    if (notation.empty())
        return 0;

    numbers.push(stoi(notation[0]));

    for (int i = 1; i < notation.size(); i+=2)
    {
        while (!operators.empty() && getPrecedence(operators.top()) >= getPrecedence(notation[i]))
            performOperation(numbers, operators);

        numbers.push(std::stoi(notation[i+1]));
        operators.push(notation[i]);
    }

    while (!operators.empty())
        performOperation(numbers, operators);

    return numbers.top();
}

std::vector<std::string> parse(const std::string& input)
{
    std::vector<std::string> vec;

    std::string current;

    for (char c : input)
    {
        if (isdigit(c))
            current += c;
        else if (c)
        {
            if (!current.empty())
            {
                vec.emplace_back(std::move(current));
                current = "";
            }

            if (c != ' ')
                vec.emplace_back(1, c);
        }
    }

    if (!current.empty())
        vec.push_back(std::move(current));

    return vec;
}

int main() {

    // This program doesn't validate input.
    // It assumes that the input is always correct.

    std::string input;
    std::getline(std::cin, input);
    std::vector<std::string> notation = parse(input);
    std::cout << RPN(notation) << '\n';
}

Ввод:

1 + 2 + 3 * 3 + 3 / 3 + 5 - 4

Выход:

14

Для простоты я беру количество строк, которые программа прочитает перед тем, как принять вход.


Обновление:

В приведенном выше коде предполагается, что входными данными является выражение infix. Если ввод уже находится в RPN, код будет таким:

#include <iostream>
#include <vector>
#include <stack>

int calculate(int a, int b, const std::string &operation)
{
    if (operation == "+")
        return a + b;
    if (operation == "-")
        return a - b;
    if (operation == "*")
        return a * b;
    if (operation == "/")
        return a / b;
    return -1;
}

bool isOperation(const std::string& op)
{
    return op == "+" || op == "-" || op == "*" || op == "/";
}

int RPN(std::vector<std::string> &notation) {

    std::stack<int> numbers;
    for (const auto& str : notation)
    {
        if (isOperation(str))
        {
            int n2 = numbers.top(); numbers.pop();
            int n1 = numbers.top(); numbers.pop();

            numbers.push(calculate(n1, n2, str));
        }
        else
            numbers.push(std::stoi(str));
    }

    return numbers.top();
}

std::vector<std::string> parse(const std::string& input)
{
    std::vector<std::string> vec;

    std::string current;

    for (char c : input)
    {
        if (isdigit(c))
            current += c;
        else if (c)
        {
            if (!current.empty())
            {
                vec.emplace_back(std::move(current));
                current = "";
            }

            if (c != ' ')
                vec.emplace_back(1, c);
        }
    }

    if (!current.empty())
        vec.push_back(std::move(current));

    return vec;
}

int main() {

    // This program doesn't validate input.
    // It assumes that the input is always correct.

    std::string input;
    std::getline(std::cin, input);
    std::vector<std::string> notation = parse(input);
    std::cout << RPN(notation) << '\n';
}
...