我的第二年编程课程存在问题,涉及创建一组代表医院的双重链表,以及医院的医生和患者。医院有一份医生名单,每位医生都有一份患者名单。我的问题是,当我调用“hireDoctor”功能将医生添加到医院的列表时,不知何故头指针正在改变。这是我的代码:
/* adds a Doctor to the Hospital's list of Doctors */
void Hospital::hireDoctor(Doctor *doc)
{
DoctorNode node;
node.value = *doc;
DoctorNode* curr;
if (drListHead == NULL) { //if doctor list is empty,
drListHead = &node; //insert the node at the beginning
node.next = NULL;
node.prev = NULL;
} else {
curr = drListHead;
//traverse list until equal or greater (alphabetical) value is found:
while (curr->value.getLast().compare(node.value.getLast()) < 0 &&
curr->value.getFirst().compare(node.value.getFirst()) < 0) {
curr = curr->next;
}
if (curr->prev == NULL) { //if inserting at the beginning of the list
drListHead = &node;
node.prev = NULL;
node.next = curr;
} else if (curr->next == NULL) { //if the end of the list has been reached
curr->next = &node;
node.prev = curr;
node.next = NULL;
} else { //insert the new DoctorNode in the middle:
curr->next->prev = &node;
node.next = curr->next;
curr->next = &node;
node.prev = curr;
}
}
列表中的每个节点都定义为结构:
struct DoctorNode {
Doctor value;
DoctorNode *next;
DoctorNode *prev;
}
所以经过一次雇佣医生的功能,如果我“聘请”一位名叫约翰史密斯的医生,我希望drListHead指向John Smith,这似乎就是这样。然而,在第二次通过该功能,雇用Jane Doe时,似乎drListHead在进入该功能时已经已经指向Jane Doe。我无法弄清楚它在哪里被改变了。任何想法都将不胜感激!
答案 0 :(得分:1)
问题出在这里:
if (drListHead == NULL) { //if doctor list is empty,
drListHead = &node; //insert the node at the beginning <------
node.next = NULL;
node.prev = NULL;
}
您的节点在堆栈上初始化,退出hireDoctor
后,它将指向堆栈的地址。下次再次呼叫hireDoctor
节点时,指向同一地址即Jane Doe(这只是一个巧合)。你需要这个:
if (drListHead == NULL) { //if doctor list is empty,
drListHead = new DoctorNode(); //heap allocation
drListHead->next = NULL;
drListHead->prev = NULL;
}
但请记住,你必须实现释放未使用的内存。
答案 1 :(得分:0)
问题在于:
DoctorNode node;
这样你的节点就可以在函数中看到它;当函数结束时,该变量被销毁。
因为被破坏的变量是可重复使用的ram,但是在这个ram没被其他东西使用之前不会改变,你认为仍然有正确的值。
下一个医生创建要求一些公羊,并且“随便”与之前医生相同的公羊免费并用于新医生。这意味着你已经把头部指向的ram重新编号,也丢失了老医生的所有数据(好吧,数据仍在这里,只是你没有更多的指针,所以它在某处丢失了RAM;这在技术上称为“垃圾”)。
寻找“变量可见性”以获得更好的解释
解决方案是改为指针
DoctorNode node*;
使用“new”来保留ram,直到你通过调用“delete”显式释放该ram。如果你在没有释放使用“删除”分配的所有指针的情况下销毁医生,那么你也在制造垃圾。 见http://www.codeproject.com/Articles/6555/To-new-is-C-To-malloc-is-C-To-mix-them-is-sin
一个常见的问题是用垃圾填充RAM,导致程序甚至操作系统崩溃。