【问题标题】:Error: deque iterator not dereferenceable错误:双端队列迭代器不可取消引用
【发布时间】:2013-06-03 08:41:28
【问题描述】:

我正在尝试创建一个将算术表达式从中缀转换为后缀形式的程序。只要我不调用“infixToPostFix”函数,程序就可以正常运行。 但是当我尝试运行以下代码时,我得到一个崩溃和错误“deque iterator not dereferenceable”。我找不到任何取消引用运算符,所以我不确定出了什么问题:

// infixToPostfixTest.cpp

#include "Token.h"
#include <iostream>
#include <vector>
#include <stack>
using namespace std;

// infix to postfix function prototype

void infixToPostfix(vector<Token> &infix, vector<Token> &postfix);

// priority function prototype
int priority(Token & t);

// printing a Token vector
void printTokenVector(vector<Token> & tvec);

int main() {

  // Experiment
  //--------------------------------------------------
  vector<Token> infix;

  // a + b * c - d / e % f
  //
  infix.push_back(Token(VALUE,5.0));   // a
  infix.push_back(Token(OPERATOR,'+'));
  infix.push_back(Token(VALUE,6.0));   // b
  infix.push_back(Token(OPERATOR,'*'));
  infix.push_back(Token(VALUE,7.0));   // c

  cout << "Infix expression: ";
  printTokenVector(infix);


  vector<Token> postfix;  // create empty postfix vector
  infixToPostfix(infix, postfix);  // call inToPost to fill up postfix vector from infix vector

  cout << "Postfix expression: ";
  printTokenVector(postfix);
  cout << endl << endl;

  return 0;
}

// printing a Token vector
void printTokenVector(vector<Token> & tvec)
{
    int size = tvec.size();
    for (int i = 0; i < size; i++) {
        cout << tvec[i] << " ";
    }
    cout << endl;
}




int priority(Token & t) // assumes t.ttype is OPERATOR, OPEN, CLOSE, or END
{
    char c = t.getChar();
    char tt = t.getType();

    if (c == '*'    ||    c == '/')
        return 2;
    else if (c == '+'    ||    c == '-')
        return 1;
    else if (tt == OPEN)
        return 0;
    else if (tt == END)
        return -1;
    else
        return -2;
}

void infixToPostfix(vector<Token> &infix, vector<Token> &postfix)
{
    stack<Token> stack;

    postfix.push_back(END);

    int looper = 0;
    int size = infix.size();
    while(looper < size) {
        Token token = infix[looper];

        if (token.getType() == OPEN)
        {
            stack.push(token); 
        }

        else if (token.getType() == CLOSE)
        {
            token = stack.top();
            stack.pop();

            while (token.getType() != OPEN)
            {
                postfix.push_back(token);

                token = stack.top();
                stack.pop();

            }
        }

        else if (token.getType() == OPERATOR)
        {
            Token topToken = stack.top();

            while ((!stack.empty()) && (priority(token) <= priority(topToken)))
            {
                Token tokenOut = stack.top();
                stack.pop();

                postfix.push_back(tokenOut);
                topToken = stack.top();
            }

            stack.push(token);
        }

        else if (token.getType() == VALUE)
        {
            postfix.push_back(token);
        }

        else
        {
            cout << "Error! Invalid token type.";
        }

        looper = looper + 1;
    }

    while (!stack.empty())
    {
        Token token = stack.top();
        stack.pop();

        postfix.push_back(token);
    }
}


//Token.h

#ifndef TOKEN_H
#define TOKEN_H

#include <iostream>
using namespace std;

enum TokenType { OPEN, CLOSE, OPERATOR, VARIABLE, VALUE, END };

class Token {

public:
    Token (TokenType t, char c) : ttype(t), ch(c) { }
    Token (TokenType t, double d) : ttype(t), number(d) { }
    Token (TokenType t) : ttype(t) { }
    Token () : ttype (END), ch('?'), number(-99999999) { }

    TokenType getType() {return ttype;}
    char getChar() {return ch;}
    double getNumber() {return number;}

private:
    TokenType ttype;
    char ch;
    double number;
};

ostream & operator << (ostream & os, Token & t) {

    switch (t.getType()) {
        case OPEN:
            os << "("; break;
        case CLOSE:
            os << ")"; break;
        case OPERATOR:
            os << t.getChar(); break;
        case VARIABLE:
            os << t.getChar(); break;
        case VALUE:
            os << t.getNumber(); break;
        case END:
            os << "END" ; break;
        default: os << "UNKNOWN";
    }


    return os;
}       

【问题讨论】:

    标签: c++ stack


    【解决方案1】:

    stack 使用container 实现,因为stackcontainer adaptor,默认使用deque。在您的代码的一行中 - 您在空的 stack 上调用 pop/top,这是不允许的。

    trace 显示,该错误在Token + 之后。 问题就在这里:

       else if (token.getType() == OPERATOR)
        {
            Token topToken = stack.top();
    

    您尝试从空的stacktop,因为stack 以防万一,其中只有NUMBER 令牌在OPERATOR 之前是空的。

    【讨论】:

    • 嗯,我在每次 pop/top 调用之前添加了一个“if (!stack.empty()),但我仍然收到错误。
    • @user1824518 你确定吗?这是唯一的原因,为什么会出现这种错误。
    • 啊,就是这样!我只搜索了“pop”关键字,所以我错过了。非常感谢
    • @user1824518 在空堆栈上调用 top() 是 UB。你真的很幸运,你的程序崩溃了。
    【解决方案2】:

    您在空堆栈上调用顶部,只需按照代码进行测试即可。

    1. 你从一个空堆栈开始
    2. 遇到 VALUE,不更改堆栈
    3. 您遇到一个 OPERATOR 并尝试访问 stack.top()

    【讨论】:

      【解决方案3】:

      我也遇到了这个问题。我认为问题出在这种代码中:

          else if (token.getType() == CLOSE)
          {
              token = stack.top();
              stack.pop();
      
              while (token.getType() != OPEN)
              {
                  postfix.push_back(token);
      
                  token = stack.top();
                  stack.pop();
      
              }
          }
      

      问题在于“token”是对顶部的引用,而不是副本。因此,在完成令牌工作之前,您不能弹出堆栈。就我而言,它通常仍然有效,因为信息仍然存在,但它会在奇怪的时间崩溃。您需要以不同的方式组织此代码,以便仅在您完成使用“令牌”后才会弹出。

      可能是这样的:

      else if (token.getType() == CLOSE)
      {
          token = stack.top();
          Token saveToken = new Token(token);  // Or something like this...
          stack.pop();
      
          while (saveToken.getType() != OPEN)
          {
              postfix.push_back(saveToken);
      
              token = stack.top();
              delete saveToken;     // ugh
              Token saveToken = new Token(token);
              stack.pop();
      
          }
          delete saveToken;  //ugh
      }
      

      【讨论】:

        猜你喜欢
        • 2014-03-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-07-13
        相关资源
        最近更新 更多