Home > other >  Linked list using main arguments
Linked list using main arguments

Time:09-27

I managed to build a linked list displaying the int that I give to it as parameters, but I can't manage to implement a linked list that displays the command line arguments.

For example, ./aout 20 40 60 80 will have as output [20] [40] [60] [80]

I think the head of the list should become the argv[1], head->next should be the argv[2] etc.

Here is my code for now :

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

typedef struct s_list t_list;

struct s_list
{
    int     value;
    t_list  *next;
};

void    add_node_end(t_list **head, int value);
void    add_node_start(t_list **head, int value);
int     remove_first(t_list **head);
int     remove_last(t_list *head);
int     remove_by_index(t_list **head, int n);
void    print_list(t_list *head);

void    add_node_end(t_list **head, int value)
{
    t_list  *current;
    current = *head;

    while (current->next != NULL)
        current = current->next;
    
    current->next = malloc(sizeof(t_list));
    current->next->value = value;
    current->next->next = NULL;
}

void    add_node_start(t_list **head, int value)
{
    t_list  *new;
    new = malloc(sizeof(t_list));
    
    new->value = value;
    new->next = *head;
    *head = new;
}

int remove_first(t_list **head)
{
    t_list  *next_node;
    int     retvalue;
    
    retvalue = -1;
    next_node = NULL;
    
    if (*head == NULL)
        return (-1);
    
    next_node = (*head)->next;
    retvalue = (*head)->value;
    free(*head);
    *head = next_node;

    return (retvalue);
}

int remove_last(t_list *head)
{
    t_list  *current;
    int     retvalue;

    retvalue = 0;

    if (head->next == NULL)
    {
        retvalue = head->value;
        free(head);
        return (retvalue);
    }
    
    current = head;
    while (current->next->next != NULL)
        current = current->next;

    retvalue = current->next->value;
    free(current->next);
    current->next = NULL;
    
    return(retvalue);
} 

int remove_by_index(t_list **head, int n)
{
    t_list  *current;
    t_list  *temp_node;
    int retvalue;
    int i;
    
    i = 0;
    retvalue = -1;
    
    if (n == 0)
        return (remove_first(head));
    
    while (i < n - 1)
    {
        if (current->next == NULL)
            return (-1);
        current = current->next;
        i  ;
    }
    temp_node = current->next;
    retvalue = temp_node->value;
    current->next = temp_node->next;
    free(temp_node);

    return(retvalue);
}

void    print_list(t_list *head)
{
    t_list  *current;
    current = head;
    
    while (current != NULL)
    {
        printf("%d\n", current->value);
        current = current->next;
    }
}

int main(void)
{
    t_list  *head;
    head = NULL;
    
    add_node_start(&head, 10);
    add_node_end(&head, 20);
    add_node_end(&head, 30);
    add_node_end(&head, 40);
    add_node_end(&head, 50);
    print_list(head);

    return (0);
}

Do you have an idea ? Thanks

CodePudding user response:

You need to change the definition of main() and you need a way to convert strings to integer (atoi(), strtol() etc):

int main(int argc, char **argv) {
    t_list  *head = NULL;
    if(argc > 1)
        add_node_start(&head, atoi(argv[1]));
    for(int i = 2; i < argc; i  )
        add_node_end(&head, atoi(argv[i]));
    print_list(head);
    return 0
}

It would be convenient to combine the implementations of add_node_start() and add_node_end() into a single function to make it easier for calling code to use. As a bonus add_node_end() does something sensible (instead of crashing) when called with head pointing to a NULL pointer:

void add_node_end(t_list **head, int value) {
    if(!*head) {
        add_node_start(head, value);
        return;
    }

    t_list  *current = *head;
    while (current->next != NULL)
        current = current->next;

    current->next = malloc(sizeof(t_list));
    current->next->value = value;
    current->next->next = NULL;
}
 
int main(int argc, char **argv) {
    t_list  *head = NULL;
    for(int i = 1; i < argc; i  )
        add_node_end(&head, atoi(argv[i]));
    print_list(head);
    return 0
}

CodePudding user response:

Off topic a bit. Good answer by @Allan Wind.

When it comes to short, simple routines, the variable names can clutter-up the landscape (possibly obscuring problems.) Here's a shorter version of one of your functions:

void print_list( t_list *p ) {
    while( p ) {
        printf( "%d\n", p->value );
        p = p->next;
    }
}

If you want the flexibility of both appending and prepending nodes to your linked list, you can combine the two functions into one by passing a third parameter. In this example, when 'atEnd' is 0 (false) the code will prepend the new node to the head of the list. (Conversely, 'appending' to the linked list if 'atEnd' is non-zero.)..

void add_node( int atEnd, t_list **head, int value ) {
    t_list *new = malloc( sizeof *new );
    /* omitting test for NULL */
    new->value = value;
    new->next = NULL;

    if( atEnd ) {
        for( t_list *p = *head; p->next; p = p->next )
            ;// just marching
        p->next = new;
    }
    else {
        new->next = *head;
        *head = new;
    }
}

Less code and fewer "special purpose" functions reduces the number of lines where bugs might be hiding.

  • Related