我目前正在研究基于链表的程序。但是我的删除功能导致程序崩溃。我想允许用户通过航班号删除航班。但是我不知道是什么原因导致崩溃的。如何解决这个问题?谢谢
struct flight {
int number;
char source[20];
char destination[20];
struct flight* next;
};
void enter();
void display();
void delete();
int count();
typedef struct flight NODE;
NODE* head_node, * first_node, * temp_node = 0, * prev_node, next_node;
int data;
char data2[20], data3[20];
void delete()
{
temp_node = (NODE*)malloc(sizeof(NODE));
temp_node = first_node;
int counter, flightno, j;
temp_node->number = data;
counter = count();
printf("\nEnter flight number to delete: \n");
scanf("%d", &flightno);
for (j = 0; j <= counter; j++)
{
if (flightno == data) {
temp_node = temp_node->next;
first_node = temp_node;
printf("\nFlight log deleted.\n");
}
else
{
printf("Flight number not found.");
}
}
}
int count()
{
int count = 0;
temp_node = first_node;
while (temp_node != 0) {
count++;
temp_node = temp_node->next;
}
return count;
}
简短回答:避免全局变量!
在delete
函数中,设置全局变量temp_node
的值。
然后您调用函数count
。在count
中,您还可以使用全局变量temp_node
。您对其进行更改,直到其值为NULL。
然后返回delete
功能,您将执行以下操作:
temp_node = temp_node->next;
取消引用NULL指针!那真的很糟糕,并且会使您的程序崩溃。
因此,开始于:摆脱所有全局变量
作为示例,您的count
函数应为:
int count(NODE* p)
{
int count = 0;
while (p != NULL) {
count++;
p = p->next;
}
return count;
}
并以类似方式调用:counter = count(first_node);
您的delete
函数可能看起来像:
NODE* delete(NODE* first_node) { ... }
那个说...
delete
函数中的原理是错误的。您无需计算节点数。简单地进行迭代,直到到达末尾,即next
为NULL。
另外-为什么malloc
功能中的delete
存储器?为什么在malloc
之后改写指针?然后就会出现内存泄漏。
temp_node = (NODE*)malloc(sizeof(NODE)); // WHY??
temp_node = first_node; // UPS... temp_node assigned new value.
// So malloc'ed memory is lost.
现在-找到匹配的节点会发生什么:
if (flightno == data) {
temp_node = temp_node->next;
first_node = temp_node; // UPS.. first_node changed
printf("\nFlight log deleted.\n");
}
然后您更改first_node。因此,当前节点之前的所有节点都丢失了!那不是你想要的。仅当匹配在链表中的第一个节点上时,您才想更改first_node
。
然后:for (j = 0; j <= counter; j++)
-> for (j = 0; j < counter; j++)
但是正如我之前所说的...不要使用这种循环。
使用类似的东西:
while (temp_node != NULL)
{
...
temp_node = temp_node->next;
}
BTW:为什么要在每个循环中进行打印?将负片打印移出循环。
A delete
功能可以通过多种方式实现。下面的示例不是最紧凑的实现,但很容易理解。
NODE* delete(NODE* head, int value_to_match)
{
NODE* p = head;
if (p == NULL) return NULL;
// Check first node
if (p->data == value_to_match)
{
// Delete first node
head = head->next; // Update head to point to next node
free(p); // Free (aka delete) the node
return head; // Return the new head
}
NODE* prev = p; // prev is a pointer to the node before
p = p->next; // the node that p points to
// Check remaining nodes
while(p != NULL)
{
if (p->data == value_to_match)
{
prev->next = p->next; // Take the node that p points to out
// of the list, i.e. make the node before
// point to the node after
free(p); // Free (aka delete) the node
return head; // Return head (unchanged)
}
prev = p; // Move prev and p forward
p = p->next; // in the list
};
return head; // Return head (unchanged)
}
并且这样称呼:
head = delete(head, SOME_VALUE);
您可能在删除功能中进行了额外的循环。您应该检查是否要删除不属于链接列表的节点。