为什么删除函数会在 C 中的链表上出错
Why deleting function gives error on linked-list in C
我目前正在开发一个基于链表的程序。但是我的删除功能导致我的程序崩溃。我想允许用户通过航班号删除航班。但我不知道是什么原因导致崩溃。如何解决这个问题?谢谢
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;
}
顺便说一句:为什么要在每个循环中打印出来?将负片打印出循环。
一个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);
我目前正在开发一个基于链表的程序。但是我的删除功能导致我的程序崩溃。我想允许用户通过航班号删除航班。但我不知道是什么原因导致崩溃。如何解决这个问题?谢谢
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;
}
顺便说一句:为什么要在每个循环中打印出来?将负片打印出循环。
一个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);