为什么删除函数会在 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);