简体   繁体   English

问题 C++ 逆波兰表示法计算器

[英]Problem C++ Reverse Polish Notation calculator

I have a problem with RPN.我对 RPN 有疑问。 I want the program to finish entering characters after pressing ENTER but something doesn't work because it doesn't write to vec.我希望程序在按 ENTER 后完成输入字符,但有些东西不起作用,因为它没有写入 vec。 I tried to solve the task: The value of the expression recorded in Reverse Polish Notation should be determined.我试图解决这个任务:应该确定以逆波兰表示法记录的表达式的值。 The expression will contain the following operators: +, -, * and / (integer division) and natural numbers not greater than one million.该表达式将包含以下运算符:+、-、* 和 /(整数除法)和不大于一百万的自然数。 The result is in the type int.结果是 int 类型。

Entrance In the first and only line the phrase written in Reverse Polish Notation.入口 在第一行也是唯一一行,用逆波兰符号书写的短语。 Operators are separated from numbers by a space character.运算符与数字之间用空格字符分隔。 Expression length is less than 1000 characters.表达式长度小于 1000 个字符。

Exit The end value of the ONP expression.退出 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;
}

Your code doesn't maintain precedence.您的代码不保持优先级。 It treats addition the same way it treats multiplication.它处理加法的方式与处理乘法的方式相同。 If that's what you want, you can just perform each operation from left to right.如果这是您想要的,您可以从左到右执行每个操作。

I suppose the goal of your program is to have some precedence and to perform for example multiplication before addition.我想你的程序的目标是有一些优先级并在加法之前执行例如乘法。

Here is a simple code that maintains precedence.这是一个保持优先级的简单代码。 The code assumes that the input is always correct and do not handle parentheses for simplicity.该代码假定输入始终正确,并且为简单起见不处理括号。

#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';
}

Input:输入:

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

Output: Output:

14

For simplicity, I take the number of strings that the program will read before taking the input.为简单起见,我采用程序在输入之前将读取的字符串数。


Update:更新:

The above code assumes that the input is an infix expression.上面的代码假设输入是一个中infix表达式。 If the input is already in the RPN , the code would be like this:如果输入已经在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';
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM