Search code examples
clinked-listfgetssingly-linked-list

Using fgets and linked lists


I am trying to get user input from fgets() and save the entry into a linked list but it isn't saving the entry into the linked lists, but if I directly put it in the call, it does. ex. add_to_list(&list, "hello"); How do use fgets to save into a character array (called word), which I can stick into add_to_list call?

    void
    add_to_list(struct linked_list *list, char *x)
    {
        struct node *n = malloc(sizeof *n);
        n->data = x;
        n->next = NULL;
        if (list->head == NULL)
            list->head = n;
        if (list->tail != NULL)
            list->tail->next = n;
        list->tail = n;
    }

    int
    main(void)
    {
        struct linked_list list = { .head = NULL, .tail = NULL };
        char word[50];

        do {
            printf("Enter string: ");
            fgets(word, 50, stdin)
            add_to_list(&list, word);
        } while (word[0] != '\n');

        //add_to_list(&list, "hello");
        print_list_rec(&list);
        free_list(&list);
        return 0;
    }

Solution

  • Here is the problem:

    n->data = x;
    

    This statement assigns the pointer to the buffer to the data pointer of the list. However, this is the same pointer in all calls. Moreover, the buffer is in the automatic storage, because word is a local variable.

    In order to fix this problem you need to add copying of the string into dynamically allocated buffers. Use strlen to decide how much memory you need, strcpy to copy the data, and don't forget to free the string after you are done with the struct.

    size_t len = strlen(x);
    n->data = malloc(len+1);
    strcpy(n->data, x);
    

    This goes inside free_list:

    free(n->data);
    free(n);