how to read multiple lines from stdin and store it in linked list

Viewed 771

I'm trying to write a program that get's lines from the user (from STDIN) and store them in a linked list.

right now I'm getting only one line and terminate the program. how can I change the code to keep getting lines from stdin?

also, if someone can tell me if I'm allocating and freeing memory as it should be it will be very helpful.

Thanks.

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

int BUFF_SIZE = 128;

struct Node {
    char* data;
    struct Node* next;
};

struct Node* head = NULL;
struct Node* tail = NULL;

void free_list(struct Node* head)
{
    if (head != NULL)
    {
        free_list(head->next);
        free(head);
    }
}

int main()
{
    int curr_size = 0;

    char* pStr = malloc(BUFF_SIZE);
    curr_size = BUFF_SIZE;

    printf("%s", "please print multiple lines\n");
    if (pStr != NULL)
    {
        char c;
        int i = 0;

        while ((c = getchar()) != '\n' && c != EOF)
        {
            pStr[i++] = c;

            if (i == curr_size)
            {
                curr_size = i + BUFF_SIZE;
                pStr = realloc(pStr, curr_size);
                if (pStr == NULL) return;
            }
        }
        pStr[i] = '\0';

        struct Node* new_node = malloc(sizeof(struct Node*));
        char* new_data = malloc(sizeof(pStr));
        new_data = pStr;
        new_node->data = new_data;

        if (head == NULL)
        {
            head = new_node;
            tail = new_node;
        }

        else
        {
            tail->next = new_node;
        }
    }

    free_list(head);
}
1 Answers

Few problems:

  1. As of now you are terminating the reading upon reacieving the \n.

    if (pStr == NULL) return; //error
    
    int c;
    int i = 0;
    
    while ((c = getchar()) != EOF)
    {
       /*New word, insert into linked list*/
       if (c == '\n'){
           pStr[i] = '\0';
    
           struct Node* new_node = malloc(sizeof(*new_node));
           char* new_data = malloc(i+1);
           strcpy(new_data, pStr);
           new_node->data = new_data;
    
           if (head == NULL)
           {
                head = new_node;
                tail = new_node;
           }
           else
           {
                tail->next = new_node;
                tail = new_node;
           }
           i = 0; //Reset the index
       }
       else {
    
           pStr[i++] = c;
           if (i == curr_size)
           {
               curr_size = i + BUFF_SIZE;
               pStr = realloc(pStr, curr_size);
               if (pStr == NULL) return;
           }
       }
    }
    
  2. Memory leaks and node data will be always pointing to latest content of pStr.

    char* new_data = malloc(sizeof(pStr)); 
    new_data = pStr;   //Memory leak here
    new_node->data = new_data;
    

    change it to

    char* new_data = malloc(i+1);
    strcpy(new_data, pStr);
    new_node->data = new_data;
    

    sizeof(pStr) is size of pointer not the string length.

  3. You need to update tail after each node is inserted to list.

     else
     {
         tail->next = new_node;
     }
    

    to

     else
    {
        tail->next = new_node;
        tail = new_node;
     }
    
Related