使用 top() 时收到错误 "cannot dereference out of range deque iterator"

Recieving error "cannot dereference out of range deque iterator" when utilizing top()

我正在创建一个简单的程序来评估 post 修复表达式,但由于 "Expression: cannot dereference out of range deque iterator" 每当它到达操作数变量的赋值时,它在成功编译后不会 运行在第 24 和 26 行。当程序仅在用数字值填充堆栈后才到达该点时,为什么它 运行 不正确?

#include <iostream>
#include <stack>
#include <string>
#include <cctype>
using namespace std;

int main() 
{
    stack<int> mystack;
    string answer; 
    int result;
    string done = "Y";
    while (done == "Y" || done == "y") {
        cout << "Please enter the RPN expression to be evaluated: ";
        getline(cin,answer);
        for(int i = 0; i < answer.length(); i++) {

            if(answer[i] == ' ' || answer[i] == ':') { 
                continue;
            } 

            if (isdigit(answer[i]) == false) {
                cout << "Token = " << answer[i];
                int operand2 = mystack.top(); 
                mystack.pop();
                int operand1 = mystack.top(); 
                mystack.pop();

                cout << " Pop " << operand2 << " Pop " << operand1;

                if(answer[i] == '+') { //operation statements
                    result = operand1 + operand2;
                }
                else if(answer[i] == '-') {
                    result = operand1 - operand2;
                }
                else if(answer[i] == '*') {
                    result =  operand1 * operand2;
                }
                else if(answer[i] == '/') {
                    result = operand1 / operand2;
                }

                mystack.push(result); //result returns to stack
                cout << " Push " << result << endl;
            }
            else if(isdigit(answer[i]) == true){
                int operand = 0; 
                while(i < answer.length() && isdigit(answer[i]) == true) {
                    operand = (operand*10) + (answer[i] - '0'); 
                    i++;
                }
                i--;
                mystack.push(operand);
                cout << "Token = " << operand << " Push " << operand << endl;
            }
        }
        cout << "Token = Pop " << mystack.top() << endl << endl;
        mystack.pop();

        cout << "type 'Y' or 'y' to continue or type any other letter to quit: ";
        getline(cin, done);
    }
}

这里有一个简单的解决方法。此版本使用 int 并使用字符串堆栈。通过在整个文件中将 int 替换为 double,这可以很容易地转换为双打,

这使用 getline() 和 istringstream 来解析输入。

它还使用字符串流将数字转换为字符串并返回。

从每一行解析多个单词时必须小心。此代码将输入行重定向到 ss,一个 istringstream 对象,然后从该对象中获取标记。

此外,如果您键入“s”,这将打印堆栈。

最后,您可以用一系列 space 分隔的数字任意加载堆栈,或者您可以一次输入一个数字。输入运算符时使用堆栈。

#include <iostream>
#include <stack>
#include <string>
#include <sstream>

///////////////////////
/// top_and_pop()
/// Save the top value from a stack, and then pop the stack
/// If the stack is empty, return the string "0".
/// If the stack was not empty, return the popped element.
std::string top_and_pop(std::stack<std::string> &stack)
{
  std::string return_string;
  if (stack.empty()) {
    return_string = "0";
    std::cout << "Stack Empty, returning 0" << std::endl;

  } else {
    return_string = stack.top();

    std::cout << "Popping " << return_string << std::endl;
    stack.pop();
  }
  return return_string;
}

//////////////////////
/// is_number
/// Parse number into a int using std::stringstream.
/// If successful, then, the stringstream will be empty.
/// Return: true if the str would successfully parse as a int
bool is_number(const std::string &str)
{
  std::istringstream ss(str);
  int number;
  ss >> number;

  if (!ss.fail() && ss.eof())
    return true;

  ss >> std::ws; // not needed in this program, because we already parsed the
  // input to a single word without whitespace.  Needed for parsing a single line
  // that may contain any set of chars.

  return !ss.fail() && ss.eof();
}

/////////////////////
/// is_operator
/// return false if str is not a single character or if an operator is not found
///  acceptable operators are anyof "+-*/"
bool is_operator(const std::string &str)
{
      return (str.length() == 1 &&
        str.find_first_not_of("+-*/") == std::string::npos);
}

/////////////////////
/// string_to_int
/// convert string to int
/// Check to be sure string can convert to a int before calling
/// if conversion fails, return 0;
int string_to_int(const std::string &str)
{
  std::stringstream stream;
  int number = 0;

  stream << str;
  stream >> number;

  return number;
}

//////////////////////
/// stack_to_string
///
/// print elements of stack
std::string stack_to_string(std::stack<std::string> stack)
{
  std::string return_string;
  while (!stack.empty()) {
    return_string += stack.top() + " ";

    stack.pop();
  }
  return return_string;
}
int main()
{
  std::stack<std::string> mystack;
  std::string input_line;
  bool done = false;  /// flag to indicate that calcualtor is closing
  std::string token_str;
  int operand1, operand2, result;

  std::cout
      << "Please enter an RPN expression.  Expression may consist of any \n"
         "combination of space-separated numbers or operators.\n"
         "Operators may include '+', '-', '*', '/'.  The stack is initialized\n"
         "with an unlimited supply of zeroes.\n\n"
         "Type 's' to print the current stack.\n"
         "To exit, type a 'y'" << std::endl;

  do {
    getline(std::cin, input_line);

    std::stringstream ss(input_line);

    /// loop through all tokens in this input line
    while (ss >> token_str) {
      // Only numbers are allowed on the stack.
      // If the current token is a number, push it on the stack as a string
      if (is_number(token_str)) {
        mystack.push(token_str);
      } else if (is_operator(token_str)) {
        operand2 = (int) string_to_int(top_and_pop(mystack));
        operand1 = (int) string_to_int(top_and_pop(mystack));

        // switch does not accept string as a type, and we checked to ensure
        // it is a single character operand that is handled in the switch
        switch (token_str[0]) {
          case '+':result = operand1 + operand2;
            break;
          case '-':result = operand1 - operand2;
            break;
          case '*':result = operand1 * operand2;
            break;
          case '/':
            if (operand2 == 0) {
              std::cout << "Error: Cannot divide by zero" << std::endl;
              continue;  // don't push result, take new input.
            } else {
              result = operand1 / operand2;
            }
            break;
            // default case not needed as we already checked operator, but
            // for error checking, we include it
          default:std::cout << "Operator not found" << std::endl;
            continue;
        }
        mystack.push(std::to_string(result));
        std::cout << " Push result " << result << " " << std::endl;
      } else if ("Y" == token_str || "y" == token_str) {
        done = true;
      } else if ("stack" == token_str || "s" == token_str) {
        std::cout << "stack: ";
        std::string stack_dump = stack_to_string(mystack);
        std::cout << stack_dump << std::endl;
      } else {
        std::cout << "Invalid input." << std::endl;
      }
    }
  }
  while (!done);
}