简体   繁体   中英

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?

Created a struct node pointer and initialized it with null and then passed it to create a linked list, it works if we initialized the head pointer with malloc but dont work this way can anyone say where i am wrong??

#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;
}
  • The argument head is a copy of what is passed, so modification of that won't affect what is passed in the caller. You should pass pointers of what should be modified to have functions modify caller's local things.
  • You have to initialize p->ptr not to cause undefined behavior by using (indeterminate) value of buffer allocated via malloc() and not initialized.
  • You should print p->data , not head->data , in the function display() .
  • Casting results of malloc() family is considered as a bad practice .

Try this:

#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;
}

Other non-critical points:

  • You should check results of scanf() to check if it successfully read desired things.
  • You should check results of malloc() to check if allocation succeeded and to avoid dereferencing NULL .
  • Making loop counter i global doesn't make sense.
  • The nodes are not freed. This won't be a problem on modern OS , but memory checkers like Valgrind may warn about that.

For starters it is a bad idea to declare the global variable i

int i;

You should declare variable in minimal scopes where they are used.

Your function create does not make a sense.

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

For starters as the pointer to the head node is passed by value to the function then the function deals with a copy of the value of the original pointer. Changing the copy within the function as for example in this statement

head = p;

does not influence on the original pointer in main. It will stay unchanged.

Also there are numerous memory leaks because addresses of the allocated memory for nodes in the loop are being lost because in this statement

head->ptr = p;

they are being overwritten.

The function should do only one thing: add a new node with the specified value to the list. The for loop should be moved in the caller of the function.

The function can look the following way

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

And in main the function can be called for example the following way

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

Pay attention to that in the function display you are outputting a value stored in the head node

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

you have to write

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

Here is a demonstrative program that shows how new nodes can be added to the list.

#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;
}

The program output might look like

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

Try this:

#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;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM