C program to create and print a linked list from the command line This program will create a linked list, set the values, and print the list by using command line options.

This is my first implementation of a linked list so I'm not sure if I did it correctly. The available options are:

-a to add nodes. 

To add several nodes:-a "23 56 1" will add three nodes with the respective values

-p will print the nodes. It has to be used after -a or else it will result in an error message.

I'm not looking for any specific input, style, comments, functions used, anything.

#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;string.h&gt;
#include &lt;unistd.h&gt;

struct node{
    int value;
    struct node *next_ptr;
};

struct node *head;

void add_node(int data);
void print_nodes(void);

int main(int argc, char *argv[]){
    int c;
    long node_value;
    char *ptr;
    char *token;
    const char s[2] = " "; /*Split optarg based on this string*/

    while((c = getopt(argc, argv, "pa:")) != EOF){
        switch(c){
        case 'p':
            print_nodes();
            break;
        case 'a':
            token = strtok(optarg, s); /*Split the string*/
            while(token != NULL){
                node_value = strtol(token, &amp;ptr, 10); /*Convert each string to integer*/
                if((*ptr) != 10 &amp;&amp; (*ptr) != 0){ /*If it's not a newline or a null then invalid input*/
                    fprintf(stderr, "Invalid number: %c", *ptr);
                    exit(EXIT_FAILURE);
                }
                add_node(node_value);
                token = strtok(NULL, s);
            }
            break;
        default:
            fprintf(stderr, "Unknown option %c, available options are '-p' and 'a'", c);
            break;
        }
    }
    argc -= optind;
    argv += optind;

    return 0;
}

void add_node(int data){
    struct node *temp = head;

    if(temp == NULL){
        head = malloc(sizeof(struct node));
        head-&gt;value = data;
        head-&gt;next_ptr = NULL;
        return;
    }

    while(temp-&gt;next_ptr != NULL){
        temp = temp-&gt;next_ptr;
    }

    if((temp-&gt;next_ptr = malloc(sizeof(struct node))) == NULL){
        fprintf(stderr, "Out of memory");
        exit(EXIT_FAILURE);
    }

    temp = temp-&gt;next_ptr;
    temp-&gt;value = data;
    temp-&gt;next_ptr = NULL;
}

void print_nodes(void){
    struct node *temp = head;
    if(temp == NULL){
            printf("Linked list is empty\n");
    }
    for(temp = head; temp != NULL; temp = temp-&gt;next_ptr){
        printf("%i\n", temp-&gt;value);
    }
}


I want to add more options, sort, search, delete and file integration, but I'd like to make sure this is working correctly first.
Nice formatting, good variable and function names. I learned more about getopt() from the program (I used to have to write my own command line parsers)! Good use of system macros such as EXIT_FAILURE.

Using Typedef

If the code used typedef for the definition of node, the code might be slightly shorter and more readable:

typedef struct node{
    int value;
    struct node *next_ptr;
} Node;

Node *head;

void add_node(int data){
    Node* temp = head;

    /* ... */
}

void print_nodes(void){
    Node* temp = head;

    /* ... */
}


By using typedef a new type is created. This also might decrease the possibility of future errors by forgetting to put the struct in at some point. This stackoverflow question discusses why it might be good to use typedef.

Global Variables

Generally the use of global variables are frowned upon. When creating, reading and debugging code global variables can be affected by side affects and it can be very difficult to find where the problem is actually occurring. This stackoverflow question talks about when it is proper to use global variables.

It might be better if the global variable NODE *head was declared in main() and then passed by reference into each function that modified it, and passed by value into each function that only used it and didn't change it.

Passing head into each of the functions would make the following changed necessary:

        case 'p':
    /*+&gt;*/  print_nodes(head);      /* Pass by value */
            break;


            while(token != NULL){
                node_value = strtol(token, &amp;ptr, 10); /*Convert each string to integer*/
                if((*ptr) != 10 &amp;&amp; (*ptr) != 0){ /*If it's not a newline or a null then invalid input*/
                    fprintf(stderr, "Invalid number: %c", *ptr);
                    exit(EXIT_FAILURE);
                }
    /* ++&gt; */   add_node(node_value, &amp;head);        /* Pass by reference */
                token = strtok(NULL, s);
            }


void add_node(int data, Node **head){
    Node* temp;

    if(*head == NULL){
        *head = malloc(sizeof(struct node));
        (*head)-&gt;value = data;
        (*head)-&gt;next_ptr = NULL;
        return;
    }

    temp = *head;
    while(temp-&gt;next_ptr != NULL){
        temp = temp-&gt;next_ptr;
    }

    if((temp-&gt;next_ptr = malloc(sizeof(struct node))) == NULL){
        fprintf(stderr, "Out of memory");
        exit(EXIT_FAILURE);
    }

    temp = temp-&gt;next_ptr;
    temp-&gt;value = data;
    temp-&gt;next_ptr = NULL;
}

void print_nodes(Node* head){
    Node* temp = head;
    if(temp == NULL){
        printf("Linked list is empty\n");
    }
    for(temp = head; temp != NULL; temp = temp-&gt;next_ptr){
        printf("%i\n", temp-&gt;value);
    }
}


This example might make the program safer and easier to debug and read.

Implicit Type Conversion

My compiler flagged the following line as an implicit type conversion:

            add_node(node_value);


because node_value is declared as a long rather than int,

    long node_value;

void add_node(int data) { /* ... */


If node_value needs to be a long because that's what strtok() is returning, it might be better to either change the input type for add_node() or to explicitly cast node_value in the call:

            add_node((int) node_value);


The actual warning message I get is implicit conversion loses integer precision: 'long to int' (Xcode 8.2 on El Capitan).

Functions that might be helpful

To implement a full linked list program some functions that might be helpful are:

NodePointer new_node(int value);
NodePointer delete_node_by_value(int value, NodePointer head);
NodePointer delete_node_by_pointer(NodePointer delete_target, NodePointer head);
NodePointer find_node(int value, NodePointer head);
void print_node(int value, NodePointer head);       // called by print_nodes


Use of the exit() Function

The use of the exit() function can be problematic, in a large software system that one is writing only a piece of, it would be better to return an error code from the add_node() function rather than call exit. In some cases such as operating systems calling exit() can have dire
consequences (shut down).

The C programming language was originally created to implement operating
systems and in some cases is still used for that purpose. While C doesn't have the exception throwing capabilities of C++, Java, C# and other more modern languages errors can be handled, either by returning error codes or using setjmp() and longjmp().