1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | #include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
#include <string.h>
#include "clog.h"
// This was made in office hours 4/8/2022
typedef struct {
int x;
int y;
} Point;
typedef struct _Node { // canonical type name is 'struct _Node'
void* a_value; // address of ANYTHING
struct _Node* next;
} Node; // shortcut (typedef) name is 'Node'
void print_list_as_addresses(Node* head) {
for(Node* curr = head; curr != NULL; curr = curr -> next) {
printf("[%p]", (void*) curr -> a_value); // v3 - linked list of anything
printf(curr -> next != NULL ? "→" : "\n");
}
}
void append(void* a_value, Node** a_head, Node** a_tail) {
// 1. Allocate memory for the new node.
Node* new_tail = malloc(sizeof(*new_tail));
// 2. Initialize the fields of the new node.
*new_tail = (Node) { .a_value = a_value, .next = NULL };
// 3. Depending on whether or not the list was initially empty…
if(*a_head == NULL) { // If list is empty (size 0)…
// … Set the head (*a_head) to the (address of) the new tail, or …
*a_head = new_tail; // type of *a_head is Node*. type of new_tail is Node*.
}
else {
// … Connect the old tail to the new tail.
(*a_tail) -> next = new_tail;
}
// 4. Set the tail (*a_tail) to the (address of the) new tail.
*a_tail = new_tail;
// IMPORTANT: This must come last.
}
void destroy_list(Node** a_head, Node** a_tail) {
while(*a_head != NULL) { // While list is not empty…
Node* new_head = (*a_head) -> next; // 1. Save (address of) new head (or NULL)
//free((*a_head) -> a_value); // 2. Free whatever head node refers to.
free(*a_head); // 3. Free the old head.
*a_head = new_head; // 4. Set the head to the new_head.
}
*a_tail = NULL; // 5. Set the tail to NULL.
// Order is important. If we free before saving the (address of) new_head, we won't
// be able to access it.
assert(*a_head == NULL);
}
void print_list_of_anything(Node const* head, void (*print_fn)(void*)) {
for(Node const* curr = head; curr != NULL; curr = curr -> next) {
printf("[");
print_fn(curr -> a_value); // Call function that prints this type of value
printf("] ");
}
printf("\n");
}
void print_point(void* a_value) {
Point* a_point = a_value; // You can freely assign a void* to a ████* and vice versa.
printf("x==%d y==%d", a_point -> x, a_point -> y);
}
void print_int(void* a_value) {
int* a_number = a_value; // You can freely assign a void* to a ████* and vice versa.
printf("%d", *a_number);
}
int main(int argc, char* argv[]) {
Node* head = NULL; // Linked list of size 0 (empty list)
Node* tail = NULL;
int input_numbers[] = { 11, 12, 13 };
size_t num_input_numbers = sizeof(input_numbers) / sizeof(input_numbers[0]);
// Populate linked list (i,e., add each element)
for(int i = 0; i < num_input_numbers; i++) {
append(&(input_numbers[i]), &head, &tail);
}
int input_numbers_idx = 0;
for(Node* curr = head; curr != NULL; curr = curr -> next) {
assert(*(int*)(curr -> a_value) == input_numbers[input_numbers_idx]);
input_numbers_idx += 1;
}
print_list_of_anything(head, print_int);
destroy_list(&head, &tail);
assert(head == NULL);
assert(tail == NULL);
return EXIT_SUCCESS;
}
|
© Copyright 2022 Alexander J. Quinn This content is protected and may not be shared, uploaded, or distributed.