user1043625 user1043625 - 23 days ago 10
C Question

Linked-list implementation

Can anyone check and see if there is an error with my linked-list implementation? I keep getting a seg fault while trying to iterate through the linked list.

I'm trying to iterate through the linked list from the "root" in "process_command" but when I try to access root->child, I'll get a seg fault error.

Implementation of the node

typedef struct _node {
struct _node *child;
char *command;
} Command_list;


The two functions that I'm using to tokenize a string and put them into a linked-list.

Command_list *process_command( char command_line[256] )
{
printf("Command: %s", command_line);

//allocate space for root & child
Command_list *root = (Command_list*)malloc(sizeof (Command_list));
Command_list *child = (Command_list*)malloc(sizeof (Command_list));

char *token;
char *saveptr;
//get the first part of the string
token = strtok_r( command_line, " ", &saveptr);

//if the first word in the string is student
if( !strcmp(token, "student") )
{
//set the first word to the be root
root = insert_command( token, root );
printf("Current root command: %s \n", root->command);
child = root;

//get the next word from the string
token = strtok_r( NULL, " ", &saveptr);

//keep getting words from the list and store them in a linked-list
while( token != NULL )
{
child = insert_command( token, child );
token = strtok_r( NULL, " ", &saveptr);
}
}
return root;
}

Command_list *insert_command( char *value, Command_list *root)
{
printf("previous value: %s \n", root->command);

Command_list *child_node = (Command_list*)malloc(sizeof (Command_list));

//if the node being passed in is empty, store the value in itself
if( root->command == NULL ){
root->command = value;
root->child = 0;
printf("Inserting value to root: %s \n", root->command);
return root;
}
//otherwise store the value in a child node
else
{
child_node->command = value;
child_node->child = 0;
printf("Inserting value to child node: %s \n", child_node->command);
return child_node;
}
}


EDIT:
Iteration code

{
....
Command_list *temp = (Command_list*)malloc(sizeof (Command_list));
temp = root;
while(temp != NULL){
printf("Command: %s\n", temp->command);
temp = temp->child;
....
}


Added the iteration code that I'm using.
The code seems to work fine in code-blocks but it stops iterating after the first output in the terminal.

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

struct node
{
 node *next;
 char *command;
};

void addNode(node **listHead, char *newData)
{
    node *newNode;

    if (*listHead == NULL)
    {
        *listHead = (node*)malloc(sizeof(node));
        newNode = *listHead;
    }
    else
    {
        newNode = *listHead;
        while (newNode->next != NULL)
            newNode = newNode->next;
        newNode->next = (node*)malloc(sizeof(node));
        newNode = newNode->next;
    }
    newNode->next = NULL;
    newNode->command = strdup(newData);
}

node *makeLinkedListOfWords(char *inputString)
{
    char *token;
    char *cmdClone;
    char *delims = " ";
    node *result = NULL;

    cmdClone = strdup(inputString);
    token = strtok(cmdClone, delims);
    while (token != NULL)
    {
        addNode(&result, token);
        token = strtok(NULL, delims);
    }
    free(cmdClone);        // EDIT: forgot to give back the duplicate string's memory
    return result;
}


void printList(node *list)
{
    int i = 0;
    while (list != NULL)
    {
        printf("%d. '%s'\n", ++i, list->command);
        list = list->next;
    }
}

int main(int argc, char *argv[])
{
    node *list1 = makeLinkedListOfWords("this is a test");
    node *list2 = makeLinkedListOfWords("so is this");
    node *list3 = makeLinkedListOfWords("and this is another");
    printList(list1);
    printList(list2);
    printList(list3);
    return 0;
}

[EDITED: SO was turning this output into an ordered list, numbered 1-11 :grrr: )

Output:

1. 'this'
2. 'is'
3. 'a'
4. 'test'
1. 'so'
2. 'is'
3. 'this'
1. 'and'
2. 'this'
3. 'is'
4. 'another'