The simplest way is the following. This prepends new items, so printing the list will yield the data in the reverse order that it was added.
Code:
#include <stdio.h>
#include <stdlib.h>
typedef struct Item {
int data;
struct Item *next;
} Item; // typedef allows us to say Item instead of struct Item
Item *listNewItem(int data, Item *next) {
Item *item = malloc(sizeof *item);
if (!item) { perror("listNewItem"); exit(EXIT_FAILURE); }
item->data = data;
item->next = next;
return item;
}
Item *listAdd(Item *list, int data) {
return listNewItem(data, list);
}
Item *listClear(Item *list) {
for (Item *next = NULL; list; list = next) {
next = list->next;
free(list);
}
return NULL;
}
int main() {
Item *list = NULL; // init list pointer to NULL
for (int i = 0; i < 10; ++i)
list = listAdd(list, i);
for (Item *item = list; item; item = item->next)
printf("%d ", item->data);
printf("\n");
list = listClear(list);
return 0;
}
If you want to add the data to the end of the list, one possibility is to search for the end each time you add an item.
Code:
#include <stdio.h>
#include <stdlib.h>
typedef struct Item {
int data;
struct Item *next;
} Item;
Item *listNewItem(int data, Item *next) {
Item *item = malloc(sizeof *item);
if (!item) { perror("listNewItem"); exit(EXIT_FAILURE); }
item->data = data;
item->next = next;
return item;
}
Item *listAdd(Item *list, int data) {
Item *item = listNewItem(data, NULL);
// If the list is empty, return item
if (!list) return item;
// Otherwise find the end of the list and append item there
Item *p = list;
for ( ; p->next; p = p->next) ;
p->next = item;
return list;
}
Item *listClear(Item *list) {
for (Item *next = NULL; list; list = next) {
next = list->next;
free(list);
}
return NULL;
}
int main() {
Item *list = NULL; // init list pointer to NULL
for (int i = 0; i < 10; ++i)
list = listAdd(list, i);
for (Item *item = list; item; item = item->next)
printf("%d ", item->data);
printf("\n");
list = listClear(list);
return 0;
}
However, searching for the end of the list every time you add an item is not very efficient. Instead, you can keep track of the "tail" of the list.
Code:
#include <stdio.h>
#include <stdlib.h>
typedef struct Item {
int data;
struct Item *next;
} Item;
typedef struct List {
Item *head;
Item *tail;
} List;
Item *listNewItem(int data, Item *next) {
Item *item = malloc(sizeof *item);
if (!item) { perror("listNewItem"); exit(EXIT_FAILURE); }
item->data = data;
item->next = next;
return item;
}
void listAdd(List *list, int data) {
Item *item = listNewItem(data, NULL);
if (list->tail)
list->tail->next = item;
else
list->head = item;
list->tail = item;
}
void listClear(List *list) {
for (Item *item = list->head, *next = NULL; item; item = next) {
next = item->next;
free(item);
}
list->head = list->tail = NULL;
}
int main() {
List list = {NULL, NULL}; // init head and tail pointers to NULL
for (int i = 0; i < 10; ++i)
listAdd(&list, i);
for (Item *item = list.head; item; item = item->next)
printf("%d ", item->data);
printf("\n");
listClear(&list);
return 0;
}