C - Simple Linked List program that handles strings

3k views Asked by At

The program specifications are pretty simple, just read in an input file of words and create a linked list where each node contains an entire string.

Here's my node struct:

typedef struct wordNode{
    char *word;
    token_type type;

    struct wordNode *next;
} wordNode;

The token type will come into play later after I get the LL basics working.

The general process of main is to open the input file, set up head with the first word, then iterate through the rest of the input file using a second node pointer, "current". Afterwards, print the list from the head pointer with a print list function.

void printList(wordNode *head)
{
    while(head != NULL)
    {
        printf("%s ", head->word);
        head = head->next;
    }

}

int main()
{
    //Open input file
    FILE *input = fopen("input.txt", "r");
    char nextWord[12] = "";

    //Scan in first word for head node
    fscanf(input, "%s", nextWord);

    //create head, fill it in with the first word, and create current
    wordNode *head = malloc(sizeof(wordNode));
    head->next = malloc(sizeof(wordNode));
    head->word = nextWord;

    printf("%s ", head->word);
    wordNode *current = head->next;

//Begin Iteration
    while(fscanf(input, "%s", nextWord) != EOF)
    {
        current = (wordNode*)malloc(sizeof(wordNode));
        current->word = nextWord;
        current->next = NULL;
        printf("%s ", current->word);
        current = current->next;
   }

    printList(head);
 }

Together, those printfs within main will give me the output I want, so the strings seem to be being saved properly during the iteration, But the output given by the printList function is the last word in the list repeated a couple times followed by garbage values.

I'm thinking head is tied to current in some way and doesn't stay put at the beginning of the list through the iteration, but I'm not sure how or why its moving.

Also, should I use strcpy for saving the strings to the nodes? I tried earlier but it was leading to crashes when I tried.

3

There are 3 answers

2
user3476093 On

You need to allocate memory for the char *s:

int main()
{
//Open input file
FILE *input = fopen("input.txt", "r");
char nextWord[12] = "";

//Scan in first word for head node
fscanf(input, "%s", nextWord);

//create head, fill it in with the first word, and create current
wordNode *head = malloc(sizeof(wordNode));
head->next = malloc(sizeof(wordNode));
head->word = (char *)calloc(strlen(nextWord) + 1);
strcpy(head->word, nextWord);

printf("%s ", head->word);
wordNode *current = head->next;

//Begin Iteration
while(fscanf(input, "%s", nextWord) != EOF)
{
    current = (wordNode*)malloc(sizeof(wordNode));
    current->word = (char *)calloc(strlen(nextWord) + 1);
    strcpy(current->word, nextWord);
    current->next = NULL;
    printf("%s ", current->word);
        current = current->next;
    }

printList(head);
}
0
user3386109 On

nextWord should either be a much larger array (e.g. nextWord[200]) or you should limit the number of characters stored by fscanf, e.g.

fscanf(input, "%11s", nextWord);

Or use a larger array and limit the number of characters.

You need to make a copy of each string after reading it into the nextWord array. The code currently just assigns the address of the nextWord array to each word pointer. So every node in the linked list points to the same string, which will be the last string read from the file. To copy a string, you need to allocate memory and then strcpy. The strdup function will do that for you, but strdup is not supported on all systems.

When the code creates the head it allocates memory for two structures. Instead, it should allocate memory for one structure and set head->next to NULL.

The variable current is a mess, e.g. you set current->next = NULL and two lines later set current = current->next. To make the code work, you need two variables, I would call them tail and current. tail should point to the last node in the linked list. So initially, tail points to head. When you create a new node, the code should look like this

    current = (wordNode*)malloc(sizeof(wordNode));
    current->word = strdup( nextWord );
    current->next = NULL;
    tail->next = current;
    tail = current;

Also, don't check fscanf for EOF. Instead, check that fscanf returns the expected number of conversions. The reason is that fscanf could get stuck in an infinite loop if a conversion fails before the end-of-file is reached. So the while loop should be

while(fscanf(input, "%11s", nextWord) == 1)
0
Hsyn On

Because you are not saving the input. Only their addresses saving in the linked list.

When you assinged head->word = nextWord the address of the nextWord which is a local aray is assigning.

You need to enough space in the struct like char Word[SIZE] or use dynamic allocation char *Word = malloc( SIZE ) and you should use strcpy to copy the input.

head->word = malloc(SIZE);
strcpy(heap->word, nextWord);

Also there is a little mistake

        wordNode *head = malloc(sizeof(wordNode));
        head->next = malloc(sizeof(wordNode)); /* (1) Allocated */
        head->word = nextWord;

        printf("%s ", head->word);
        wordNode *current = head->next; /* current points allocated memory (1) */

    //Begin Iteration
        while(fscanf(input, "%s", nextWord) != EOF)
        {
            current = (wordNode*)malloc(sizeof(wordNode)); /*re-allocation 
and (1) is allocated but not used memory you can not access it anymore*/
            current->word = nextWord;
            current->next = NULL;
            printf("%s ", current->word);
            current = current->next;
       }

        printList(head);
     }