当前位置: 首页 > 知识库问答 >
问题:

使用堆栈和队列的中缀到后缀:无法访问内存C++

马祺
2023-03-14

我正在尝试取一个不固定表达式的字符串,并将其更改为后缀。

我相信大部分代码应该可以工作,但是当queue::enqueue(char,int)被调用时会出现“无法读取内存”的问题,程序无法读取“front”或“freal”。如果我在test_driver.cpp中更改iString,我会得到相同的错误,但是在stack::empty()上。我认为这是一个与类之间的联想有关的问题。

在最后的努力中,他们交上了彼此的朋友,但我不确定这是否是正确的方法。我添加了下面的所有文件。任何帮助都将不胜感激。

   * test_driver.cpp 

*******************************************************************************/
#include <iostream>
#include "Stack.h"
#include "Queue.h"
#include "EqConverter.h"
using namespace std;

int main() {
    string inputString, resultString;
    EqConverter* testQueue= new EqConverter;

    inputString = "2+3";

    testQueue->convert_to_pf(inputString);
    resultString = testQueue->return_exp();

    cout << resultString;


 cin.get();
  delete testQueue;

  return 0;


    /*Queue* testQueue = new Queue;

    for (int i = 0; i < 100; i++)
    {
        testQueue->enqueue(i, i);
    }

    for (int i = 0; i < 100; i++)
    {
        cout<<testQueue->dequeue()->data<<endl;

    }

    delete testQueue;*/

  cin.get();
/*************************************************/  

eqconverter.cpp

    #include <iostream>
#include <string>
#include "Stack.h"
#include "Queue.h"
#include "EqConverter.h"

using namespace std;


EqConverter::EqConverter()
{
    Stack*op_stack = new Stack;
    Queue*exp_queue = new Queue;
}

EqConverter::~EqConverter()
{
    delete op_stack;
    delete exp_queue;
}

int EqConverter::convert_to_pf(string iString)
{
    // Function to verify whether a character is english letter or numeric digit. 
    // We are assuming in this solution that operand will be a single character

    //Begin Actual converting from infix to postfix//
    for (int i = 0; i < iString.length(); i++)
    {
        if (IsOperator(iString[i]))
        {
            while (!op_stack->empty() && op_stack->top()->data != '(' && HasHigherPrecedence(op_stack->top()->data, iString[i]))
            {
                exp_queue->enqueue(op_stack->top());
                op_stack->pop();
            }
            op_stack->push(iString[i], GetOperatorWeight(iString[i]));
        }
        // Else if character is an operand
        else if (IsOperand(iString[i]))
        {
            exp_queue->enqueue(iString[i], GetOperatorWeight(iString[i]));
        }

        else if (iString[i] == '(' || iString[i] == '[')
        {
            op_stack->push(iString[i], GetOperatorWeight(iString[i]));
        }

        else if (iString[i] == ')')
        {
            while (!op_stack->empty() && op_stack->top()->data != '(')
            {
                exp_queue->enqueue(op_stack->top());
                op_stack->pop();
            }
            op_stack->pop();
        }
    }

    while (!op_stack->empty())
    {
        exp_queue->enqueue(op_stack->top());
        op_stack->pop();
    }


    return 0;
}

bool EqConverter::IsOperand(char C)
{
    if (C >= '0' && C <= '9') return true;
    if (C >= 'a' && C <= 'z') return true;
    if (C >= 'A' && C <= 'Z') return true;
    return false;
}

// Function to verify whether a character is operator symbol or not. 
bool EqConverter::IsOperator(char C)
{
    if (C == '+' || C == '-' || C == '*' || C == '/' || C == '$' || C == '[' || C == '%')
        return true;

    return false;
}

// Function to verify whether an operator is right associative or not. 
int EqConverter::IsRightAssociative(char op)
{
    if (op == '$') return true;
    return false;
}


// Function to get weight of an operator. An operator with higher weight will have higher precedence. 
int EqConverter::GetOperatorWeight(char op)
{
    int weight = -1;
    switch (op)
    {
    case '(':
    case '[':
        weight = 0;
        break;
    case '+':
    case '-':
        weight = 1;
        break;
    case '*':
    case '/':
    case '%':
        weight = 2;
        break;
    case '$':
        weight = 3;
    }
    return weight;
}

// Function to perform an operation and return output. 
int EqConverter::HasHigherPrecedence(char op1, char op2)
{
    int op1Weight = GetOperatorWeight(op1);
    int op2Weight = GetOperatorWeight(op2);

    // If operators have equal precedence, return true if they are left associative. 
    // return false, if right associative. 
    // if operator is left-associative, left one should be given priority. 
    if (op1Weight == op2Weight)
    {
        if (IsRightAssociative(op1))
            return false;

        else
            return true;
    }
    return op1Weight > op2Weight ? true : false;
}

string EqConverter::return_exp()
{
    string pString;


    while (exp_queue->dequeue() != 0)
    {       
        pString.push_back(exp_queue->dequeue()->data);
    }

    return pString;
}


}

queue.cpp

#include"Node.h"
#include"Queue.h"


using namespace std;

Queue::Queue()
{
    front = new Node;
    front = 0;

    rear = new Node;
    rear = 0;
}

Queue::~Queue()
{
    destroy_Queue();
    delete front;
    delete rear;
}

void Queue::destroy_Queue()
{
    Node* temp;

    while (front!=0)
    {
        temp = front;
        front = front->link;
        delete temp;

    }
}

void Queue::enqueue(char info, int order)
{
    Node* temp;
    temp = new Node;

    temp->data = info;
    temp->precedence = order;

    if (front == 0)
    {
        front = temp;
        rear = temp;
    }
    else
    {
        rear->link = temp;
        rear = rear->link;
    }
}

void Queue::enqueue(Node* newNode)
{
    newNode = new Node;

    if (front == 0)
    {
        front = newNode;
        rear = newNode;
    }
    else
    {
        rear->link = newNode;
        rear = rear->link;
    }       
}

Node* Queue::dequeue()
{
    Node* temp;

    if (front != 0)
    {
        temp = front;
        front = front->link;
        return temp;
    }
    else
        return 0;
}

Stack.cpp

#include"Node.h"
#include"Stack.h"

using namespace std;

Stack::Stack()
{   
    tos = 0;
}

Stack::~Stack()
{
    destroy_Stack();
    delete tos;
}

void Stack::destroy_Stack()
{
    Node* temp;         //Pointer to delete the node

    while (tos != 0)    //delete the tos while it is not pointing to NULL
    {
        temp = tos;     //assign temp to "tos" so its link can be broken
        tos = tos->link;//advance "tos" to the node below it in the stack

        delete temp;    //Delete temp which pointed to the node of the previous "tos"

    }
}


Node* Stack::top() const
{
    if (tos==0)
        return 0;
    else
        return tos;
}

void Stack::push(char info, int rank)
{
    Node* newNode;
    newNode= new Node;  //create a new node to store incoming data
    newNode->data = info;       //storing the incoming char into the data of the new node
    newNode->precedence = rank; //synonym to store incoming numerical precdence into the new node
    newNode->link= tos; //link newNode to old "tos" 

    tos = newNode;   //Now that the link is created we can assign newNode as "tos"
}

void Stack::push(Node* newTop)
{
    newTop->link = tos;   //link new top node to old "tos"
    tos = newTop;       //Now that the link is created we can assign newTop as "tos"
}

Node* Stack::pop()
{
    if (tos == 0)
        return 0;

    Node* temp;
    temp= new Node; //Creates a temp node to store current "tos"
    temp = tos;             //pointer to keep track of "tos"
    tos = tos->link;        //Advances "tos" to what was stored under it

    return temp;            //Returns what "tos" was before advancing it
}

bool Stack::empty()
{
    if (tos == 0)
        return true;
    else
        return false;
}
#ifndef EQCONVERTER_H
#define EQCONVERTER_H

#include<string>

using namespace std;

class EqConverter {
  private:

    Stack *op_stack;
    Queue *exp_queue;

    //My functions for easier implementation
    bool IsOperand(char);
    bool IsOperator(char);
    int IsRightAssociative(char);
    int GetOperatorWeight(char);
    int HasHigherPrecedence(char, char);

  public:
    EqConverter();    // creates an Stack and Queue object using dynamic memory
    ~EqConverter();   // cleans up the Stack and Queue objects

    /* convert_to_pf ***********************************************************
    * iteratively traverses the string passed in and performs the steps of the 
    * conversion algorithm using the Stack and Queue; the conversion algorithm
    * is provided in the assignment statement.  You will need to provide a 
    * variable for the string parameter
    ***************************************************************************/
    int convert_to_pf(string);


    // returns a string of the converted postfix expression stored in exp_queue 
    string return_exp();  


    friend class Stack;
    friend class Queue;
};

#endif

排队

/*******************************************************************************
* Queue.h 

*******************************************************************************/
#ifndef QUEUE_H
#define QUEUE_H

#include <iostream>
#include "Node.h"

class Queue {
  private:
    Node* front;  // pointer to the front of the queue
    Node* rear;   // pointer to the rear of the queue


  public:
    Queue();  // initializes front and rear to a null pointer
    ~Queue(); // deletes all nodes in the queue; may call destroy_Queue 

    /* The enqueue method ******************************************************
    * enqueue(char, int): creates a new node and places it at the rear of the
    *     queue, you will need to provide variables for the char/int parameters  
    * 
    * enqueue(Node*): adds the passed in Node argument to the rear of the queue; 
    *     you will need to provide a variable for the Node* parameter
    ***************************************************************************/    
    void enqueue(char, int);
    void enqueue(Node*);

    /* The pop and top methods *************************************************
    * dequeue(): disconnects and returns the node at the front of the queue.  
    *     This method also updates front to point to the new front.  If the 
    *     queue is empty, it should return the null pointer.    
    ***************************************************************************/
    Node* dequeue(); 

    // iteratively traverse the linked list that makes up the queue and deletes
    // each node 
    void destroy_Queue();

    friend class EqConverter;
};

#endif

Stack.H

/*******************************************************************************
* Stack.h 

*******************************************************************************/
#ifndef STACK_H
#define STACK_H

#include "Node.h"

class Stack {
  private:
    Node *tos;  // the pointer to the Top Of Stack (TOS)

  public:
    Stack();    // does nothing more than just initialize tos to a null pointer
    ~Stack();   // deletes all nodes in the stack; may call destroy_Stack 

    /* The push method *********************************************************
    * push(char, int): creates a new node and places it on the TOS, you will 
    *     need to provide variables for the char and int parameters  
    * 
    * push(Node*): adds the passed in Node argument to the TOS; you will need
    *     to provide a variable for the Node* parameter
    ***************************************************************************/
    void push(char, int);
    void push(Node*);


    /* The pop and top methods *************************************************
    * pop(): disconnects and returns the node at the TOS; a pointer is returned.
    *     This method also updates tos to point to the new TOS.  If the stack is
    *     empty, it should return the null pointer.
    * 
    * top(): returns a pointer to the Node at the TOS. If the stack is empty,
    *     it should return the null pointer.
    ***************************************************************************/
    Node* pop();
    Node* top() const;

    // iteratively traverse the linked list that makes up the stack and deletes
    // each node 
    void destroy_Stack();

    bool empty();

    friend class EqConverter;
};

#endif

Node.H

/*******************************************************************************
* Node.h 

*******************************************************************************/
#ifndef NODE_H
#define NODE_H

struct Node {
  char data;
  int precedence;
  Node *link;

  // this overloaded operator uses a reference to a pointer variable
  bool operator < (const Node *&rhs) const {
    return this->precedence < rhs->precedence;
  }  
};

#endif

共有1个答案

申颖逸
2023-03-14

我在您的程序中使用了valgrind,它立即暴露了您的代码中的一些问题:

==15835== Use of uninitialised value of size 8
==15835==    at 0x401ABC: Queue::enqueue(char, int) (in /home/A.Romanek/tmp/programming/so-1/main)
==15835==    by 0x4013C6: EqConverter::convert_to_pf(std::string) (in /home/A.Romanek/tmp/programming/so-1/main)
==15835==    by 0x400E9E: main (in /home/A.Romanek/tmp/programming/so-1/main)
==15835== 
==15835== Invalid read of size 8
==15835==    at 0x401ABC: Queue::enqueue(char, int) (in /home/A.Romanek/tmp/programming/so-1/main)
==15835==    by 0x4013C6: EqConverter::convert_to_pf(std::string) (in /home/A.Romanek/tmp/programming/so-1/main)
==15835==    by 0x400E9E: main (in /home/A.Romanek/tmp/programming/so-1/main)
==15835==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==15835== 
==15835== 
==15835== Process terminating with default action of signal 11 (SIGSEGV)
==15835==  Access not within mapped region at address 0x0
==15835==    at 0x401ABC: Queue::enqueue(char, int) (in /home/A.Romanek/tmp/programming/so-1/main)
==15835==    by 0x4013C6: EqConverter::convert_to_pf(std::string) (in /home/A.Romanek/tmp/programming/so-1/main)
==15835==    by 0x400E9E: main (in /home/A.Romanek/tmp/programming/so-1/main)

在我看来,这个问题与队列的实现有关。它还可能与放在队列中的节点的实现有关。

不过,我还是建议使用STL中的 。这些应该对你很有帮助。

 类似资料:
  • 我的讲师给了我一个任务,创建一个程序,使用堆栈将中缀表达式转换为后缀。我制作了堆栈类和一些函数来读取中缀表达式。 但是这个名为inToPos(charstring[])的函数正在创建断点,该函数负责使用堆栈将字符串中缀中的中缀表达式转换为字符串后缀中的后缀表达式。你们能帮帮我,告诉我我做错了什么吗? 这些是我的代码,非常需要您的帮助:) 注:inToPos功能是使用以下算法实现的: 从左到右扫描中

  • 日安!我正在使用堆栈实现一个内缀到后缀转换器。当用户输入一个没有括号的内插表达式时,它可以工作;但是当存在括号时,控制台说: 我的问题是在实现排名(堆栈的顶部)。

  • 我的任务是使用单链表实现堆栈,将中缀形式的字符串转换为后缀形式。为简单起见,此字符串不包含任何空格。 简而言之,我的算法是: > 按操作顺序使用字符及其关联优先级创建临时节点 如果是操作而不是数字,则将其推到堆栈上/如果是数字,则自动将其附加到后缀字符串 每次将一个字符推送到堆栈上时,如果堆栈的顶部节点的优先级高于下一个字符的临时节点,请将其从堆栈中弹出,并将其附加到后缀字符串中。 这些步骤在手动

  • 我的讲师给了我一个任务,让我创建一个程序,使用堆栈将表达式和中缀转换为后缀。我制作了堆栈类和一些函数来读取中缀表达式。 但是这个函数,叫做,它负责使用堆栈将数组inFix中的inFix表达式转换为数组postFix中的postfix表达式,并没有做它应该做的事情...你们能帮帮我告诉我哪里做错了吗? 下面是从中缀转换为后缀的函数的代码,是我需要帮助修复的代码: 注意:convertToPostfi

  • 我正在为我的一堂计算机科学课开发一个计算后缀表达式结果的程序。该程序使用堆栈ADT来实现这一点。 我已经编写了程序,但相信可能会有错误,因为一些表达式的结果不正确。我不确定我的错误在哪里。 此外,当输入文件为空时,程序将生成一个值32767。那是从哪里来的? 表达式:34+3*值=21。 主程序:

  • 我写了一个中缀式转化为后缀式,前缀式,并计算出中前后缀式结果的代码,但是在确保输入格式正确后(我输入的是:11+22*(9-6)/3#),输出为:Have no target!!,我想了好久,觉得是输入的式子没有办法入栈,但是找不出来哪里有问题,能帮我看一下是哪里的问题吗?谢谢各位大佬! 以下是我的代码: 主函数中将 改为 输出变成了“The Sqstack2 is empty!” 试过修改ini