【问题标题】:Why i am not able to assign a struct node pointer with allocated memory to a struct node pointer with previous value of null for making a linked list?为什么我无法将分配内存的结构节点指针分配给先前值为 null 的结构节点指针以创建链表?
【发布时间】:2021-04-30 12:03:35
【问题描述】:

创建了一个结构节点指针并用 null 初始化它,然后传递它来创建一个链表,如果我们用 malloc 初始化头指针,它就可以工作,但不能这样工作,谁能说我错在哪里??

#include <stdio.h>
#include <stdlib.h>
int i;
struct node
{
    int data;
    struct node *ptr;
};

void create(struct node *head, int n)
{
    for (i = 0; i < n; i++)
    {
        struct node *p = (struct node *)malloc(sizeof(struct node));
        scanf("%d", &p->data);
        if (head == NULL)
            head = p;
        else
        {
            head->ptr = p;
        }
    }
}
void display(struct node *head)
{
    struct node *p = head;
    if (head == NULL)
    {
        printf("Empty Linked List");
        return;
    }
    else
    {
        while (p != NULL)
        {
            printf("%d", head->data);
            p = p->ptr;
        }
    }
}

int main()
{
    struct node *head = NULL;
    int n;
    scanf("%d", &n);
    create(head, n);
    display(head);
    return 0;
}

【问题讨论】:

  • 那么问题出在哪里? struct node 定义在哪里?
  • @MrMischievousX This if (head->ptr == NULL) head->data = p->data;否则 { 头->ptr = p; } 没有意义并产生内存泄漏。
  • @VladfromMoscow 你能纠正我吗?
  • 例如输入3 1 2 3的期望输出是什么?
  • @MikeCAT 1 2 3 应该输出

标签: c struct linked-list singly-linked-list function-definition


【解决方案1】:
  • 参数head 是传递的副本,因此对其进行修改不会影响调用者中传递的内容。您应该传递 指针 应该修改的内容以使函数修改调用者的本地内容。
  • 您必须使用通过malloc() 分配且未初始化的缓冲区的(不确定)值来初始化p-&gt;ptr,以免导致未定义的行为
  • 您应该在函数display() 中打印p-&gt;data,而不是head-&gt;data
  • malloc() 家庭的投射结果是considered as a bad practice

试试这个:

#include <stdio.h>
#include <stdlib.h>
int i;
struct node
{
    int data;
    struct node *ptr;
};

void create(struct node **head, int n) /* receive pointer */
{
    /* go to the end of list */
    while (*head != NULL)
    {
        head = &(*head)->ptr;
    }

    for (i = 0; i < n; i++)
    {
        struct node *p = malloc(sizeof(struct node)); /* don't cast results of malloc() */
        scanf("%d", &p->data);
        p->ptr = NULL; /* initialize p->ptr */
        *head = p; /* dereference the pointer to update list */
        head = &p->ptr; /* go to the next place to append node */
    }
}
void display(struct node *head)
{
    struct node *p = head;
    if (head == NULL)
    {
        printf("Empty Linked List");
        return;
    }
    else
    {
        while (p != NULL)
        {
            printf("%d", p->data); /* output correct thing */
            p = p->ptr;
            if (p != NULL) putchar(' '); /* add space for proper output */
        }
    }
}

int main(void) /* use standard signature */
{
    struct node *head = NULL;
    int n;
    scanf("%d", &n);
    create(&head, n); /* pass pointer */
    display(head);
    return 0;
}

其他非关键点:

  • 您应该检查scanf() 的结果以检查它是否成功读取所需的内容。
  • 您应该检查malloc() 的结果以检查分配是否成功并避免取消引用NULL
  • 将循环计数器 i 设为全局没有意义。
  • 节点未释放。 This won't be a problem on modern OS,但像 Valgrind 这样的内存检查器可能会对此发出警告。

【讨论】:

  • 非常感谢您解决问题并提供其他宝贵资源
【解决方案2】:

对于初学者来说,声明全局变量 i 是个坏主意

int i;

您应该在使用它们的最小范围内声明变量。

你的函数create没有意义。

void create(struct node *head, int n)
{
    for (i = 0; i < n; i++)
    {
        struct node *p = (struct node *)malloc(sizeof(struct node));
        scanf("%d", &p->data);
        if (head == NULL)
            head = p;
        else
        {
            head->ptr = p;
        }
    }
}

对于初学者来说,指向头节点的指针通过值传递给函数,然后函数处理原始指针值的副本。更改函数内的副本,例如在此语句中

head = p;

不影响 main 中的原始指针。它将保持不变。

还有很多内存泄漏,因为在这个语句中,为循环中的节点分配的内存地址丢失了

head->ptr = p;

它们正在被覆盖。

该函数应该只做一件事:将具有指定值的新节点添加到列表中。应该在函数的调用者中移动 for 循环。

函数可以如下所示

int create( struct node **head, int data )
{
    struct node *p = malloc( sizeof( struct node ) );
    int success = p != NULL;

    if ( success )
    {
        p->data = data;
        p->ptr = *head;
        *head = p;
    }

    return success;
}

并且在 main 中可以通过以下方式调用该函数

struct node *head = NULL;
int n;
scanf( "%d", &n );

int success = 1;

for ( int i = 0; success && i < n; i++ )
{
    int data;
    scanf( "%d", &data );    
    success = create( &head, data );
}

请注意,在函数显示中,您正在输出存储在头节点中的值

printf("%d", head->data);

你必须写

printf("%d", p->data);

这是一个演示程序,展示了如何将新节点添加到列表中。

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

struct node
{
    int data;
    struct node *ptr;
};

int create( struct node **head, int data )
{
    struct node *p = malloc( sizeof( struct node ) );
    int success = p != NULL;

    if ( success )
    {
        p->data = data;
        p->ptr = *head;
        *head = p;
    }

    return success;
}

FILE * display( const struct node *head, FILE *fp )
{
    for ( ; head != NULL; head = head->ptr )
    {
        fprintf( fp, "%d -> ", head->data );
    }
    
    fputs( "null", fp );
    
    return fp;
}

int main(void) 
{
    struct node *head = NULL;
    
    size_t n = 0;
    
    printf( "Enter the number of nodes you want to add to the list: " );
    scanf( "%zu", &n );
    
    srand( ( unsigned int )time( NULL ) );
    
    int success = 1;
    for ( size_t i = 0; success && i < n; i++ )
    {
        success = create( &head, rand() % ( int )( 2 * n ) );
    }
    
    fputc( '\n', display( head, stdout ) );
    
    return 0;
}

程序输出可能看起来像

Enter the number of nodes you want to add to the list: 10
11 -> 16 -> 10 -> 18 -> 9 -> 0 -> 8 -> 1 -> 3 -> 18 -> null

【讨论】:

  • 您的代码将从输入3 1 2 3 创建一个列表3 2 1,而不是根据需要创建一个1 2 3。 (除非您修复了display() 函数,否则它将打印为333
  • @MikeCAT 输入是谁想要的?由你?例如,你为什么不能写 3 3 2 1?!
【解决方案3】:

试试这个:

#include <stdio.h>
#include <stdlib.h>
int i;
struct node
{
    int data;
    struct node *ptr;
};

void create(struct node *head, int n)
{
    struct node *p = head;
    for (i = 0; i < n; i++)
    {
        scanf("%d", &p->data);
        if(i<n-1)
        {
            struct node *temp = (struct node *)malloc(sizeof(struct node));
            temp->ptr=NULL;
            p->ptr=temp;
            p=temp;
        }
    }
}
void display(struct node *head)
{
    struct node *p = head;
    if (head == NULL)
    {
        printf("Empty Linked List");
        return;
    }
    else
    {
        while (p != NULL)
        {
            printf("%d", p->data);
            p = p->ptr;
        }
    }
}
int main()
{
    struct node *head = (struct node *)malloc(sizeof(struct node));
    head->ptr = NULL;
    int n;
    scanf("%d", &n);
    create(head, n);
    display(head);
    return 0;
}

【讨论】:

    猜你喜欢
    • 2023-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-23
    • 1970-01-01
    • 1970-01-01
    • 2015-12-22
    • 2023-04-06
    相关资源
    最近更新 更多