为什么删除功能在C中的链表上给出错误

问题描述 投票:1回答:2

我目前正在研究基于链表的程序。但是我的删除功能导致程序崩溃。我想允许用户通过航班号删除航班。但是我不知道是什么原因导致崩溃的。如何解决这个问题?谢谢

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;
}
c loops if-statement linked-list structure
2个回答
3
投票

简短回答:避免全局变量!

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);

1
投票

您可能在删除功能中进行了额外的循环。您应该检查是否要删除不属于链接列表的节点。

© www.soinside.com 2019 - 2024. All rights reserved.