【问题标题】:C programming error in code [closed]代码中的 C 编程错误 [关闭]
【发布时间】:2018-08-08 02:55:29
【问题描述】:
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>

struct student
{
    int ID;
    int age;
    struct student *next;
};

struct student *head = 0;
struct student *first = 0;
struct student *temp = 0;

void create_list()
{
    static int counter = 1;
    head = (struct student *)malloc(sizeof(struct student));
    printf("Enter the student no. %d ID\n",counter);
    scanf_s("%d", &head->ID);
    printf("Enter the student no. %d age\n", counter);
    scanf_s("%d", &head->age);
    if (first != 0)
    {
        temp->next = head;
        temp = head;
    }
    else
    {
        first = temp = head;
    }

    counter++;
}

void read_list()
{
    temp->next = 0;

    temp = first;
    int counter = 1;
    first = 0;
    while (temp != 0)
    {
        printf("------------------Node number : %d---------------\n", counter);
        printf("The Student id is : %d\n", temp->ID);
        printf("The Student age is : %d\n", temp->age);
        counter++;
        temp = temp->next;
    }
    printf("NULL\n");
    printf("-------------No. of nodes in the list = %d\n------------------", counter);
}

void delete_list(struct student **head, int position)
{

    if (*head == NULL)
        return;

    struct student* temp = *head;

    if (position == 0)
    {
        *head = temp->next;   
        temp = 0;               
        return;
    }

    for (int i = 0; temp != NULL && i<position - 1; i++)
        temp = temp->next;

    if (temp == NULL || temp->next == NULL)
        return;

    struct student *next = temp->next->next;

    temp->next=0;  
    temp->next = next;  
}

void main()
{

    int choice = 0;
    while (choice != 99)
    {
        printf("Please enter a choice from the list:\n");
        printf("1- Create Node\n");
        printf("2- Read List\n");
        printf("3- Delete Node\n");
        printf("99- Exit\n");
        scanf_s("%d", &choice);
        switch (choice)
        {
        case 1:
            create_list();
            break;
        case 2:
            read_list();
            break;
        case 3:
            delete_list(&head,2);
            break;
        }
    }

}

我的删除功能遇到了很多问题。我正在创建一个链接节点列表。我创建了读取和创建函数,但是每当我尝试删除一个节点并移回所有节点时,它都会给我一个错误。我可以就问题所在寻求帮助吗?

错误是每当我再次打印列表时,它就会停止并且不打印任何内容。

【问题讨论】:

  • 错误是什么?请提供minimal reproducible example
  • 请注意,&lt;stdlib.h&gt; 声明了 malloc() 等,因此不需要非标准的 &lt;malloc.h&gt;,除非您使用它的一些额外功能,而您没有使用。你没有概述你输入的值——或者你得到的错误输出。这是 MCVE (minimal reproducible example) 的重要组成部分。我们不应该猜测。调试时,您可以在每次操作后调用read_list() 函数。
  • 你的全局变量temp令人担忧;我不清楚它是如何使用的。对您来说似乎很重要,因为您在删除代码中仔细设置了它,但为什么呢?同样,全局变量next 可能不应该是全局变量。使用全局变量head 是允许的——它通常不是最好的选择,但没关系。这意味着您一次只能使用此代码管理一个列表,但是当您刚开始时,这没关系。在类 Unix 系统上使用 void main() 无效;正确的返回类型是int。 Windows 文档void main() 所以它不会自动出错。
  • 你为什么用delete_list(&amp;head,2); 固定2? delete_list 的预期行为是什么?只是删除最后一个节点?
  • @F.Igor 我将其设置为示例,因此如果我输入 5 个节点作为示例并删除了第 2 个节点,它会将它们向后移动 1 个步骤,并且会在没有第 2 个节点的情况下再次打印 4 个节点

标签: c linked-list


【解决方案1】:

如果有更多问题请不要怀疑与我联系。祝你好运。

关于 createlist()

Head 应该指向列表的第一个元素,但是您使用 head 来实例化添加到列表中的最新元素。 First 和 head 在概念上是相同的。我认为您认为 head 应该是列表的最后一个元素,但它不应该。阅读有关链表的更多信息。你也是从温度指向头部吗?但是等等,什么是温度?你能告诉我你程序中那个时候的温度是多少吗?你不应该依赖 temp,这就是为什么它被称为 temp。它应该是一个时间变量。不是全局变量。

关于 read_list()

为什么 temp-> next = 0?你可能会在这里打破你的链条,因为我们不知道 temp 是什么。让我们继续。因此,您指向列表中的第一个元素(应该与 head 相同)。我的天啊!您首先指向空值。当然,您不能将列表阅读两次或三次。一旦您首先指向 null,您将失去对列表第一个元素的唯一引用。你用你的其他功能做什么都没关系。您将无法连续两次调用此函数,您的代码将中断。

我的意思是。第一次通过时,请先执行 temp =。然后首先 = NULL

第二次。温度=第一。但是...首先= null?摇铃?您将无法打印其他任何内容。

while 循环没问题。

关于 delete_list()

好吧,你把我弄丢了。您现在正在使用头部。但我可以告诉你,head 绝对不是指向列表中的第一个元素。如果有的话,它是列表中的最后一个元素,并且(head->next = random stuff)并且如果幸运的话(head->next = null)。我不确定,但如果 head 指向列表中的第一个元素(但不是),这个函数可能没问题或接近没问题。但是不要相信我的话,我现在真的很累。

总结:

你的函数是错误的。破坏代码的功能不止一个,而是很多。你的主要问题是你用指针搞砸了。如果我是你,我会:

  • 删除 first 和 temp 作为全局变量。
  • 查看链表Linked Lists
  • 在函数中使用 temp 作为局部变量。
  • 释放分配的内存,并在分配时检查是否有错误。
  • head 应始终指向列表中的第一个元素。您不应该更新 head,除非您将第一个元素添加到列表中或删除最后一个元素。
  • 您应该更新 head 的唯一情况是在列表的开头添加一个元素,但我鼓励您先尝试制作没有此功能的程序。

如果您分配内存(例如,calloc 或 malloc),您应该始终释放该内存并将指针指向 NULL(这是一个好习惯)。您的编程方式正在泄漏内存。

您也不应该将 temp 作为全局变量。如果您不使用它,它可能会产生您不会遇到的问题。同样拥有三个全局变量会使事情更难审查或调试。当您应该拥有的唯一全局变量是 head。

如果你想检查它,我为你的代码写了一个替代方案。

代码说明:

我不检查用户输入,但它可以很容易地添加到主函数中。 有 5 个函数:addLastElement、addFirstElement、deleteList、deleteElement 和 readList。

  • readList:打印列表。

  • addLastElement:如果没有元素,它将添加头部。如果有 是元素,它将在列表末尾添加一个新元素。它 除非 head 为空,否则不会更新 head。

  • addFirstElement:在列表的开头添加一个元素。这 函数总是更新头部。

  • deleteElement:删除作为参数传递的位置的元素。 它会释放内存。

  • deleteList:将从列表中删除所有元素并释放 记忆。

除 readList 之外的所有函数都会相应地更新结构列表的变量“大小”。

#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>

struct student
{
    int id;
    int age;
    struct student *next;
};

struct list
{
    struct student *head;
    int size;
};

void addFirstElement(struct list *list, int id, int age)
{
    struct student *temp;
    temp = (struct student *)malloc(sizeof(struct student));
    if (temp == NULL)
    {
        printf("Error: Couldn't allocate memory\n");
    }
    temp -> id = id;
    temp -> age = age;
    temp->next = list -> head;
    list->head = temp;
    list->size++;
}

void addLastElement(struct list *list, int id, int age)
{
    struct student *new;
    struct student *temp;
    new = (struct student *)malloc(sizeof(struct student));
    if (new == NULL)
    {
        printf("Error: Couldn't allocate memory\n");
    }
    new->id = id;
    new->age = age;
    new->next = NULL;
    if (list->head == NULL)
    {
        list->head = new;
    }
    else
    {
        temp = list -> head;
        while (temp->next != NULL)
        {
            temp = temp->next;
        }
        temp->next = new;
    }
    list->size++;
}

void readList(struct list *list)
{
    struct student *temp = list->head;

    while (temp != NULL)
    {
        printf("ID: %d - Age: %d\n", temp->id, temp->age);
        temp = temp->next;
    }
}

void deleteList(struct list *list)
{
    struct student *temp;
    struct student *previous;

    temp = list->head;
    while (temp != NULL)
    {
        previous = temp;
        temp = temp->next;
        free(previous);
    }
    previous = NULL;
    list->size = 0;
    list->head = NULL;
}

void deleteElement(struct list *list, int position)
{
    if (list->head == NULL)
        return;

    if (position < 0 || position > ((list->size) - 1))
    {
        printf("The list is not that big\n");
        return;
    }

    struct student *temp = list->head;
    struct student *previous = NULL;
    int i = 0;

    temp = list->head;
    while (i != position)
    {
        previous = temp;
        temp = temp->next;
        i++;
    }

    if (previous == NULL)
    {
        list->head = list->head->next;
    }
    else
    {
        previous->next = temp->next;
    }
    list->size--;
    free(temp);
    temp = NULL;
    return;
}
int main()
{
    struct list list;
    int i;
    list.size = 0;
    list.head = NULL;

    for (i = 0; i < 10; i++)
    {
        addLastElement(&list, i, (i+1)*10);
    }

    deleteElement(&list, 5);

    addFirstElement(&list, 100, 50);

    readList(&list);

    deleteList(&list);

    return 1;
}

输出:

ID: 100 - Age: 50
ID: 0 - Age: 10
ID: 1 - Age: 20
ID: 2 - Age: 30
ID: 3 - Age: 40
ID: 4 - Age: 50
ID: 6 - Age: 70
ID: 7 - Age: 80
ID: 8 - Age: 90
ID: 9 - Age: 100

【讨论】:

    【解决方案2】:

    create_list() 中的代码不会检查内存分配是否成功。它也不能可靠地设置next 元素。这意味着如果您添加 5 个节点并打印它们,您将只能看到列表中最近添加的节点。因为列表构造不正确,所以您的删除代码没有太大的工作机会(它对我来说崩溃了,而且我懒得找出确切的原因;这可能是因为取消引用空指针)。一个关键问题是混淆了headfirst 的角色——first 确实指向列表的第一个元素,但从未更新,head 没有指向列表中的第一个元素, 与正常惯例相反。正如 cmets 中已经指出的,temp 主要是令人困惑的——它不应该作为全局变量存在。这是你的问题的一个主要因素。

    这是另一种实现方式。它不提示输入;添加 5 个学生然后将其全部删除是硬连线的。它使用head 作为指向列表中第一个结构的单个全局变量。它在列表的开头添加新元素。添加或删除每个学生后,它会打印列表,以便进行完整检查。打印时,每个学生使用一行。当学生被删除时,它会释放内存。

    #include <assert.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    struct student
    {
        int ID;
        int age;
        struct student *next;
    };
    
    struct student *head = 0;
    
    static void create_list(int ID, int age)
    {
        struct student *node = (struct student *)malloc(sizeof(struct student));
        if (node == 0)
        {
            fprintf(stderr, "Failed to allocate %zu bytes\n", sizeof(*node));
            exit(EXIT_FAILURE);
        }
        node->ID = ID;
        node->age = age;
        node->next = 0;
        if (head != 0)
            node->next = head;
        head = node;
    }
    
    static void print_list(void)
    {
        int counter = 0;
        for (struct student *node = head; node != 0; node = node->next)
        {
            printf("-- Node %2d: ID = %.5d, age = %d\n", ++counter, node->ID, node->age);
        }
        printf("-- No. of nodes in the list = %d\n\n", counter);
    }
    
    static void delete_list(int position)
    {
        int counter = 0;
        struct student *node = head;
        struct student *prev = 0;
        while (node != 0 && ++counter != position)
        {
            prev = node;
            node = node->next;
        }
    
        if (node == NULL)
            return;
        if (prev == NULL)
        {
            assert(node == head);
            struct student *old = head;
            head = head->next;
            free(old);
        }
        else
        {
            assert(node != head);
            prev->next = node->next;
            free(node);
        }
    }
    
    int main(void)
    {
        create_list(10102, 19);
        print_list();
        create_list(23147, 20);
        print_list();
        create_list(30001, 21);
        print_list();
        create_list(47721, 18);
        print_list();
        create_list(59286, 20);
        print_list();
        delete_list(2);
        print_list();
        delete_list(3);
        print_list();
        delete_list(2);
        print_list();
        delete_list(1);
        print_list();
        delete_list(1);
        print_list();
        return 0;
    }
    

    示例输出:

    -- Node  1: ID = 10102, age = 19
    -- No. of nodes in the list = 1
    
    -- Node  1: ID = 23147, age = 20
    -- Node  2: ID = 10102, age = 19
    -- No. of nodes in the list = 2
    
    -- Node  1: ID = 30001, age = 21
    -- Node  2: ID = 23147, age = 20
    -- Node  3: ID = 10102, age = 19
    -- No. of nodes in the list = 3
    
    -- Node  1: ID = 47721, age = 18
    -- Node  2: ID = 30001, age = 21
    -- Node  3: ID = 23147, age = 20
    -- Node  4: ID = 10102, age = 19
    -- No. of nodes in the list = 4
    
    -- Node  1: ID = 59286, age = 20
    -- Node  2: ID = 47721, age = 18
    -- Node  3: ID = 30001, age = 21
    -- Node  4: ID = 23147, age = 20
    -- Node  5: ID = 10102, age = 19
    -- No. of nodes in the list = 5
    
    -- Node  1: ID = 59286, age = 20
    -- Node  2: ID = 30001, age = 21
    -- Node  3: ID = 23147, age = 20
    -- Node  4: ID = 10102, age = 19
    -- No. of nodes in the list = 4
    
    -- Node  1: ID = 59286, age = 20
    -- Node  2: ID = 30001, age = 21
    -- Node  3: ID = 10102, age = 19
    -- No. of nodes in the list = 3
    
    -- Node  1: ID = 59286, age = 20
    -- Node  2: ID = 10102, age = 19
    -- No. of nodes in the list = 2
    
    -- Node  1: ID = 10102, age = 19
    -- No. of nodes in the list = 1
    
    -- No. of nodes in the list = 0
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-22
      • 2011-09-23
      • 1970-01-01
      • 2013-12-21
      • 1970-01-01
      • 2013-01-25
      相关资源
      最近更新 更多