我正在为我的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只与我的棋盘图形在控制台上的方式有关。由于它适用于所有其他节点(不包括头部),因此我将其排除为错误源。选择器是一个检查对象,但它不是列表的一部分。
这是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;
}
}
}
}
答案 0 :(得分: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
答案 1 :(得分: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;
}
}
我希望有所帮助。花点时间将问题分解成更小的部分,找出可能的情况,如何处理它们,然后才开始编写代码。
答案 2 :(得分:0)
根据问题作者的this edit,他使用的解决方案是:
我修改了代码以显示检查器删除中传递的地址 功能。
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; } } } }