0

我正在为我的 C++ 课程开发一个跳棋模拟游戏。我的问题是包含检查器的链接列表。除了列表的头部之外,我可以完美地删除任何检查器。我环顾了这里和其他网站,我相信某处存在内存泄漏。我对 C++ 还很陌生,所以除了玩弄一些东西(这可能只会造成更大的问题)之外,我不知道该做什么。我以前从来没有在这里发过帖子,所以如果格式有点不对或太乱,请原谅。我会尽量简短。首先,这是链表的节点类的片段。

class CheckerpieceNode 
{
private:
    Checkerpiece *Node;
    CheckerpieceNode *Next;
public:
    CheckerpieceNode(); // sets Node and Next to NULL in .cpp file
    void setNode(Checkerpiece *node);
    void setNext(CheckerpieceNode *next);
    Checkerpiece* getNode();
    CheckerpieceNode* getNext();
}; 

并且功能的设置与您在 Checkerpiece.cpp 类中所期望的一样。以下是代码的使用方式。它由我的主类中的 Checkerboard 对象调用。

 theCheckerboard.removeChecker(theCheckerboard.findChecker(selector->getCurrentX() + 0, selector->getCurrentY() - VERTICAL_SHIFT, listHead), listHead);

VERTICAL_SHIFT 只是与我的棋盘图形在控制台上的方式有关。由于它适用于所有其他节点(不包括头部),我已将其排除为错误来源。Selector 是一个棋盘格对象,但它不是列表的一部分。

这是 Checkerboard 类中实际的 findChecker 和 removeChecker 代码。

Checkerpiece* findChecker(int x, int y, CheckerpieceNode* list_head)
{
if(list_head== NULL) return NULL; // do nothing
else
{
    CheckerpieceNode* node = new CheckerpieceNode;
    node = list_head;
    while(node != NULL && node->getNode() != NULL)
    {
        if()// comparison check here, but removed for space
        {
            return node->getNode(); 
            delete node; 
            node = NULL;
        }
        else // traversing
            node = node->getNext();
    }

    return NULL; 
}
}


void removeChecker(Checkerpiece* d_checker, CheckerpieceNode* list_head)
{
if(list_head== NULL) // throw exception
else
{
    CheckerpieceNode *temp = NULL, *previous = NULL;
    Checkerpiece* c_checker= new Checkerpiece;
    temp = list_head;
    while(temp != NULL && temp->getNode() != NULL)
    {
        c_checker= temp->getNode();
        if(d_checker!= c_checker) 
        {
            previous = temp;
            temp = temp->getNext();
        }
        else
        {
            if(temp != list_head)
            {
                previous->setNext(temp->getNext());
                delete temp;
                temp = NULL;
            }
            else if(temp == list_head) // this is where head should get deleted
            {   
                temp = list_head;
                list_head= list_head->getNext();
                delete temp;
                temp = NULL;
            }


            return;
        }
    }
}
}
4

3 回答 3

0

根据问题作者的此编辑,他使用的解决方案是:

我修改了代码以显示在检查器删除函数中传递的地址。

void delete_checker(Checker* d_checker, CheckerNode* &list_head) // pass by address
{
if(list_head== NULL) // throw exception
else
{
    CheckerNode*temp = NULL, *previous = NULL;
    Checker* c_checker= new Checker; 
    temp = list_head;
    while(temp != NULL && temp->node!= NULL)
    {
        c_checker= temp->node;
        if(d_checker!= c_checker) 
        {
            previous = temp;
            temp = temp->next;
        }
        else
        {
            if(temp != list_head)
            {
                previous->next = temp->next;
                delete temp;
                temp = NULL;
            }
            else if(temp == list_head) // this is where head should get deleted
            {    
                temp = list_head;
                list_head= list_head->next;
                delete temp;
                temp = NULL;
            }

                     delete c_checker; 
                     c_checker = nullptr;

            return;
        }
    }
}
}
于 2013-10-24T17:38:44.570 回答
0

removeChecker 无法修改 list_head 的值,因为它是按值过去的。方法签名应该是:

void removeChecker(Checkerpiece* d_checker, CheckerpieceNode** list_head)
// You will need to call this function with &list_head

或者

void removeChecker(Checkerpiece* d_checker, CheckerpieceNode* &list_head)
// Calling code does not need to change
于 2013-10-19T01:58:02.547 回答
0

哦,我的,你把它复杂化了。大量冗余检查、赋值和不必要的变量(比如c_checker也会泄漏内存)。

// Write down the various scenarios you can expect first:
// (a) null inputs
// (b) can't find d_checker
// (c) d_checker is in head
// (d) d_checker is elsewhere in the list
void removeChecker(Checkerpiece* d_checker, CheckerpieceNode* list_head) {
   // first sanitize your inputs
   if (d_checker == nullptr || list_head == nullptr) // use nullptr instead of NULL. its a keyword literal of type nullptr_t
       throw exception;

   // You understand that there is a special case for deleting head. Good.
   // Just take care of it once and for all so that you don't check every time in the loop.
   CheckerpieceNode *curr = list_head;

   // take care of deleting head before traversal
   if (d_checker == curr->getNode()) {
       list_head = list_head->next; // update list head
       delete curr; // delete previous head
       return; // we're done
   }

   CheckerpieceNode *prev = curr;
   curr = curr->next;

   // traverse through the list - keep track of previous
   while (curr != nullptr) {
       if (d_checker == curr->getNode()) {
           prev->next = curr->next; 
           delete curr;
           break;    // we're done!
       }

       prev = curr;
       curr = curr->next;
   }
}

我希望这会有所帮助。花时间把问题分解成更小的部分,找出可能的场景,你将如何处理它们,然后才开始编写代码。

于 2013-10-19T01:59:44.587 回答