简体   繁体   English

C ++堆栈实现(作业)PT。 II

[英]C++ stack implementation (homework) PT. II

OK making progress here. 确定在这里取得进展。 My question is now related to copy construction and deep-copy. 我的问题现在与复制构造和深复制有关。 My stack is currently crashing all the time and I have a feeling that it is doing so because the class it is dependent on doesn't allow copy construction and operator overloading. 我的堆栈当前一直在崩溃,我有一种感觉,因为它所依赖的类不允许复制构造和操作符重载。 But anyway here is my code (I apologize for the amount of code but it is probably necessary to understand where i am failing): 但是无论如何这是我的代码(我为代码量表示歉意,但可能有必要了解我的失败之处):

The dependent class, linked list 依赖类,链表

#ifndef linkList_H
#define linkList_H


//
// Create an object to represent a Node in the linked list object
// (For now, the objects to be put in the list will be integers)
//
struct Node
{
    int   number;
    Node* next;
    Node* prev;

    // needs copy constructor?
    // needs overloaded assignment operators for copying?
    // needs overloaded operators for incrementing and decrementing?
};


//
// Create an object to keep track of all parts in the list
//
class List
{
public:

    //
    // Contstructor intializes all member data
    //
    List() : m_size(0), m_listHead(0) {}

    //
    // methods to return size of list and list head
    //
    Node*    getListHead() const { return m_listHead; }
    unsigned getListSize() const { return m_size; }

    //
    // methods for adding and inserting a new node to the linked list, 
    // retrieving and deleting a specified node in the list
    //
    void  addNode(int num);
    void  deleteNode(Node* current);
    void  insertHead(Node* current);
    void  insertAfter(Node* current, int newValue);
    void  insertBefore(Node* current, int newValue);

    Node* retrieveNode(unsigned position);

private:

    //
    // member data consists of an unsigned integer representing
    // the list size and a pointer to a Node object representing head
    //
    Node*    m_listHead;
    unsigned m_size;
};

#endif

Implementation of linkedList 实现LinkedList

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

using namespace std;


//
// Adds a new node to the linked list
//
void List::addNode(int num)
{
    Node *newNode = new Node;
    newNode->number = num;
    newNode->next = m_listHead;

    if( m_listHead )
        m_listHead->prev = newNode;

    m_listHead = newNode;
    ++m_size;
}


//
// Inserts a node which has already been set to front
// of the list
//
void List::insertHead(Node* current)
{
    int value = current->number;
    deleteNode(current);
    addNode(value);
}


//
// Inserts a node which has already been set before a
// specified location in the list
//
void List::insertBefore(Node* current, int newValue)
{
    current = current->prev;
    current->number = newValue;
}


//
// Inserts a node which has already been set before a
// specified location in the list
//
void List::insertAfter(Node* current, int newValue)
{
    current = current->next;
    current->number = newValue;
}


//
// Deletes a node from a specified position in linked list
//
void List::deleteNode(Node* current)
{
    --m_size;

    if(current == m_listHead) 
        m_listHead = current->next;
    if(current->prev) 
        current->prev->next = current->next;
    if(current->next) 
       current->next->prev = current->prev;
}


//
// Retrieves a specified node from the list
//
Node* List::retrieveNode(unsigned position)
{
    if(position > (m_size-1) || position < 0)
    {
        cout << "Can't access node; out of list bounds";
        cout << endl;
        cout << endl;

        exit(EXIT_FAILURE);
    }

    Node* current = m_listHead;
    unsigned pos = 0;

    while(current != 0 && pos != position)
    {
        current = current->next;
        ++pos;
    }

    return current;
}

Here is the stack class: 这是堆栈类:

#ifndef stack_H
#define stack_H

#include "linkList.h"


class Stack
{
public:

    //
    // Constructor, copy constructor and destructor to initialize stack 
    // data, copy data and clear up memory, respectively
    //
   Stack() : m_top(0), m_stack(new List()) {}
   Stack(const Stack &rhs);

   ~Stack() { delete [] m_stack; }

    //
    // functionality to determine if stack is empty
    //
    bool isEmpty();

    //
    // methods for pushing data on to stack and for
    // popping data from the stack
    //
    void push(int newValue);
    int  pop();

    //
    // accessor functions for retrieving the value on top of stack
    // and for returning the stack size
    //
    int getTop() const { return m_top->number; }
    int getSize() const { return m_stack->getListSize(); }

    //
    // overloaded assignment operator for copying stack
    //
    Stack& operator=(const Stack &rhs);

private:

    //
    // member data which represent the stack, the top
    // of the stack and the size of the stack
    //
    Node* m_top;
    List* m_stack;
};

#endif

And finally, here is the stack implementation 最后,这是堆栈实现

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

using namespace std;

//
// Copy constructor
//
Stack::Stack(const Stack &rhs)
    : m_top(rhs.m_top), m_stack(rhs.m_stack)
{
}

//
// if the Top of stack is zero, return true
//
bool Stack::isEmpty()
{
    if( m_top == 0 ) return true;
    else return false;
}

//
// increment stack pointer, place new value in stack
//
void Stack::push(int newValue)
{
    ++m_top;               
    m_top->number = newValue;   // crashes on this statement
}

//
// if the stack is empty, throw an error message
//
int Stack::pop()
{
    if( isEmpty() )
    {
        cout << "Error: stack underflow" << endl;
        exit(EXIT_FAILURE);
    }

    --m_top;
    return (m_top + 1)->number;

}


Stack& Stack::operator=(const Stack &rhs)
{
    if( this != &rhs )
        delete [] m_stack;

    m_stack = new List();
    m_stack = rhs.m_stack;
    m_top = rhs.m_top;

   return *this;
}

Program crashes after this simple code in the main program: 在主程序中执行以下简单代码后,程序崩溃:

Stack stack;

stack.push(1);

Again, sorry for the amount of code here. 同样,对这里的大量代码感到抱歉。 I believe my problem here is that the Node object needs overloaded operators in order to "increment" or "decrement" to create/delete a node when a value is being pushed/popped to the stack. 我相信我的问题在于,当将值压入/弹出到堆栈中时,Node对象需要重载运算符,以便“增加”或“减少”来创建/删除节点。 Is this the case? 是这样吗 Also, I am not sure if I need a copy constructor or not for the Node object. 另外,我不确定Node对象是否需要复制构造函数。 There could be many more problems here (maybe the algorithms are incorrect? maybe copy construction is incorrect for stack?). 这里可能还有更多问题(也许算法不正确?也许堆栈的拷贝构造不正确?)。 Any ideas? 有任何想法吗?

Lets take your crashing scenario line-by-line. 让我们逐行处理崩溃的情况。 (good, cause it only has 2 lines!) (很好,因为它只有两行!)
First the statement: Stack stack; 首先声明: Stack stack;
This will call the stack-constructor, which will set m_top to what value? 这将调用堆栈构造函数,它将m_top设置为什么值?

Next, there's the line: stack.push(1); 接下来是一行: stack.push(1);
The two statements of stack.push will both use m_top . stack.push的两个语句stack.push将使用m_top
The first statement is ++m_top; 第一条语句是++m_top;
Given what value m_top started with, what value will it have now? 给定m_top最初的值是m_top ,现在它将具有什么值?

The second statement is m_top->number = newValue; 第二条语句是m_top->number = newValue;
If you answered the previous questions about m_top correctly, it should be clear why the program is crashing at this point. 如果您正确回答了有关m_top的先前问题,那么应该清楚为什么程序此时会崩溃。 It should also be relatively clear how to fix it. 还应该相对清楚如何解决它。

m_top is set to 0 in your constructor. m_top在您的构造函数中设置为0 But... 但...

Your Stack just needs to decorate your List in a very specific manner. 您的Stack仅需要以非常特定的方式装饰List From looking briefly at your List header, it all should be relatively easy to implement, if you understand how a stack works... 如果您了解堆栈的工作原理,那么从简短地查看List头开始,这一切都应该相对容易实现...

Your Stack doesn't need to hold a "top". 您的Stack不需要保持“顶部”。 It should be implemented in terms of your List . 应该根据您的List来实现。 Pushing onto the stack should add a new node at the front of your list, and popping from the stack should remove a node from the front of your list. 推入堆栈应在列表的前面添加一个新节点,而从堆栈弹出则应从列表的前面删除一个节点。

First of all, you can't use the array delete operator on m_stack ( delete [] m_stack ) because there is only a single object there not an array ( m_stack = new List ). 首先,您不能在m_stack( delete [] m_stack )上使用数组删除运算符,因为只有一个对象而没有数组( m_stack = new List )。 This will cause a crash. 这将导致崩溃。 (Actually I don't see why it's created dynamically.) (实际上,我不明白为什么它是动态创建的。)

Then, you will need to write a proper assignment operator and copy constructor for your List class, which will copy the nodes, and also a destructor which clean up the allocated nodes, but this has nothing to do with your crash (but will easily cause you in the future). 然后,您将需要为List类编写一个适当的赋值运算符并复制构造函数,以复制节点,并使用析构函数清理分配的节点,但这与崩溃无关(但很容易导致崩溃将来的您)。

The current cause of the crash, is like the others said, that Stack tries access m_top while it's being null. 导致崩溃的当前原因,就像其他人所说的那样,Stack尝试在m_top为空时访问m_top。

But the main problem is bad design which makes you use the List class in an unclear way :/ 但是主要的问题是不良的设计,这使您无法清楚地使用List类:/

  • First, if you have a two-way linked list, the List class should also track the tail pointer not just the head pointer. 首先,如果您有双向链接列表,则List类还应该跟踪尾指针,而不仅仅是头指针。 This will free you from a lot a head-aches. 这将使您免于头痛。
  • Then, addHead, addTail, insertBefore, insertAfter should not rely on the user to create the nodes, but create them inside the functions and return the newly created node. 然后, addHead, addTail, insertBefore, insertAfter不应依赖用户来创建节点,而应在函数内部创建它们并返回新创建的节点。
  • Also it is very unsafe that the next and prev pointers are exposed and can be changed outside the List class. 同样,公开nextprev指针并且可以在List类之外进行更改也是非常不安全的。 I suggest you the make prev and next private and expose a getter for them, so they could not be changed (List class will need to be friend of the Node struct/class in this case). 我建议您将make prev和next私有,并为它们公开一个getter,这样就不能更改它们(在这种情况下,List类需要成为Node struct / class的朋友)。

I think, these will give you good start how to re-write List and Stack from scratch. 我认为,这些将为您重新开始如何重新编写List和Stack提供一个良好的开端。 Also, keep an eye out for the ownership of the nodes which is not handled now. 另外,请注意尚未处理的节点的所有权。

您在构造函数m_top初始化为0 (空),然后尝试在push()使用它

Best approach is to test these classes one at a time. 最好的方法是一次测试这些课程。 Since Stack depends on List, debug list first. 由于堆栈取决于列表,因此请首先调试列表。 I'm assuming that you have a access to a debugger. 我假设您可以访问调试器。 If not get one and learn how to use it. 如果没有得到,并学习如何使用它。 You also need to write some test code for the List class. 您还需要为List类编写一些测试代码。

Good luck. 祝好运。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM