【问题标题】:Problem C++ Reverse Polish Notation calculator问题 C++ 逆波兰表示法计算器
【发布时间】:2020-05-29 12:34:59
【问题描述】:

我对 RPN 有疑问。 我希望程序在按 ENTER 后完成输入字符,但有些东西不起作用,因为它没有写入 vec。 我试图解决这个任务: 应确定以逆波兰表示法记录的表达式的值。该表达式将包含以下运算符:+、-、* 和 /(整数除法)和不大于一百万的自然数。结果是 int 类型。

入口 在第一行也是唯一一行中,用逆波兰符号书写的短语。运算符与数字之间用空格字符分隔。表达式长度小于 1000 个字符。

退出 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;
}

【问题讨论】:

    标签: c++ vector rpn


    【解决方案1】:

    您的代码不保持优先级。它处理加法的方式与处理乘法的方式相同。如果这是您想要的,您可以从左到右执行每个操作。

    我想你的程序的目标是有一些优先级并在加法之前执行例如乘法。

    这是一个保持优先级的简单代码。该代码假定输入始终正确,并且为简单起见不处理括号。

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

    【讨论】:

    • @beginnerDevLucas 我已经更新了答案,这样输入就不必分开了。
    • StackExchange123 - 抱歉,我的错误 - 我误解了您的输入 :) 现在一切正常。谢谢
    • hmm 我有一个小问题:对于输入 5 6 8 4 * + / 2 + 抛出错误“在抛出一个无效参数后调用终止 // what() stoi
    • 这个程序接受一个中缀表达式并将其转换为后缀表达式(RPN)然后执行计算。您的输入采用后缀表示法。它必须是中缀符号。
    • @beginnerDevLucas 我已经更新了答案,以便您可以直接输入RPN
    猜你喜欢
    • 2021-11-29
    • 1970-01-01
    • 2021-12-24
    • 1970-01-01
    • 2020-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-15
    相关资源
    最近更新 更多