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

Posted

技术标签:

【中文标题】问题 C++ 逆波兰表示法计算器【英文标题】:Problem C++ Reverse Polish Notation calculator 【发布时间】: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;

【问题讨论】:

【参考方案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

以上是关于问题 C++ 逆波兰表示法计算器的主要内容,如果未能解决你的问题,请参考以下文章

逆波兰表达式

C语言 逆波兰表达式 算法

逆波兰表示法

逆波兰算术表达式 C语言

每周算法题---逆波兰表示法,求该后缀表达式的计算结果

C++栈的应用:逆波兰式的实现