From 1a1cb9f122f2eb10b21c93d635af81f06b5381d5 Mon Sep 17 00:00:00 2001 From: Owen Dorweiler Date: Thu, 27 Mar 2025 12:36:49 -0400 Subject: [PATCH] Homework 07: Initial Import --- homework07/Makefile | 66 +++++++++++++++++++ homework07/list.c | 50 ++++++++++++++ homework07/list.h | 41 ++++++++++++ homework07/list.unit.c | 143 +++++++++++++++++++++++++++++++++++++++++ homework07/node.c | 31 +++++++++ homework07/node.unit.c | 83 ++++++++++++++++++++++++ homework07/seqit.c | 34 ++++++++++ homework07/tailit.c | 34 ++++++++++ 8 files changed, 482 insertions(+) create mode 100644 homework07/Makefile create mode 100644 homework07/list.c create mode 100644 homework07/list.h create mode 100644 homework07/list.unit.c create mode 100644 homework07/node.c create mode 100644 homework07/node.unit.c create mode 100644 homework07/seqit.c create mode 100644 homework07/tailit.c diff --git a/homework07/Makefile b/homework07/Makefile new file mode 100644 index 0000000..d86360b --- /dev/null +++ b/homework07/Makefile @@ -0,0 +1,66 @@ +CC= gcc +CFLAGS= -Wall -g -std=gnu99 +LD= gcc +LDFLAGS= -L. +TARGETS= seqit tailit + +all: $(TARGETS) + +#-------------------------------------------------------------------------------- +# TODO: Add rules for node.o, list.o, seqit.o, tailit.o, seqit, tailit +#-------------------------------------------------------------------------------- + +node.o: + +list.o: + +seqit.o: + +tailit.o: + +seqit: + +tailit: + +#------------------------------------------------------------------------------- +# DO NOT MODIFY BELOW +#------------------------------------------------------------------------------- + +test: + @$(MAKE) -sk test-all + +test-all: test-gitignore test-node test-list test-seqit test-tailit + +test-gitignore: + @echo "*.o" >> .gitignore + @echo "*.sh" >> .gitignore + @echo "*.unit" >> .gitignore + +node.unit: node.unit.c node.o + $(LD) $(LDFLAGS) -o node.unit node.unit.c node.o + +test-node: node.unit + @curl -sLO https://www3.nd.edu/~pbui/teaching/cse.20289.sp25/static/txt/homework07/node.unit.sh + @chmod +x node.unit.sh + @./node.unit.sh + +list.unit: list.unit.c node.o list.o + $(LD) $(LDFLAGS) -o list.unit list.unit.c node.o list.o + +test-list: list.unit + @curl -sLO https://www3.nd.edu/~pbui/teaching/cse.20289.sp25/static/txt/homework07/list.unit.sh + @chmod +x list.unit.sh + @./list.unit.sh + +test-seqit: seqit + @curl -sLO https://www3.nd.edu/~pbui/teaching/cse.20289.sp25/static/txt/homework07/seqit.test.sh + @chmod +x seqit.test.sh + @./seqit.test.sh + +test-tailit: tailit + @curl -sLO https://www3.nd.edu/~pbui/teaching/cse.20289.sp25/static/txt/homework07/tailit.test.sh + @chmod +x tailit.test.sh + @./tailit.test.sh + +clean: + @rm -f *.o *.unit *.unit.sh *.test.sh seqit tailit diff --git a/homework07/list.c b/homework07/list.c new file mode 100644 index 0000000..303c7e3 --- /dev/null +++ b/homework07/list.c @@ -0,0 +1,50 @@ +/* list.c: List Structure */ + +#include "list.h" + +/* List Functions */ + +/** + * Create a List structure. + * + * @return Pointer to new List structure (must be deleted later). + **/ +List * list_create() { + // TODO + return NULL; +} + +/** + * Delete List structure. + * + * @param l Pointer to List structure. + * @param release Whether or not to release the string values. + **/ +void list_delete(List *l, bool release) { + // TODO +} + +/** + * Add new Value to back of List structure. + * + * @param l Pointer to List structure. + * @param v Value to add to back of List structure. + **/ +void list_append(List *l, Value v) { + // TODO +} + +/** + * Remove Value at specified index from List structure. + * + * @param l Pointer to List structure. + * @param index Index of Value to remove from List structure. + * + * @return Value at index in List structure (-1 if index is out of bounds). + **/ +Value list_pop(List *l, size_t index) { + // TODO + return (Value)-1L; +} + +/* vim: set sts=4 sw=4 ts=8 expandtab ft=c: */ diff --git a/homework07/list.h b/homework07/list.h new file mode 100644 index 0000000..78e51d0 --- /dev/null +++ b/homework07/list.h @@ -0,0 +1,41 @@ +/* list.h: Doubly Linked List Library */ + +#pragma once + +#include +#include +#include + +/* Value Union */ + +typedef union { + int64_t number; // Value as number + char *string; // Value as string +} Value; + +/* Node Structure */ + +typedef struct Node Node; +struct Node { + Value value; // Value + Node *next; // Pointer to next Node + Node *prev; // Pointer to previous Node +}; + +Node * node_create(Value v, Node *next, Node *prev); +void node_delete(Node *n, bool release); + +/* List Structure */ + +typedef struct { + Node sentinel; // Sentinel Node at head and tail of List + size_t size; // Number of Nodes in List +} List; + +List * list_create(); +void list_delete(List *l, bool release); + +void list_append(List *l, Value v); +Value list_pop(List *l, size_t index); + +/* vim: set sts=4 sw=4 ts=8 expandtab ft=c: */ diff --git a/homework07/list.unit.c b/homework07/list.unit.c new file mode 100644 index 0000000..b565b1c --- /dev/null +++ b/homework07/list.unit.c @@ -0,0 +1,143 @@ +/* list.unit.c: List Structure Unit Test */ + +#include "list.h" + +#include +#include +#include +#include +#include + +/* Constants */ + +const int64_t NUMBERS[] = {5, 7, 4, -1}; +const char *STRINGS[] = {"Orange", "South Bend", "Eau Claire", NULL}; + +/* Tests */ + +int test_00_list_create() { + List *l = list_create(); + assert(l); + assert(l->sentinel.value.number == 0); + assert(l->sentinel.next == &l->sentinel); + assert(l->sentinel.prev == &l->sentinel); + assert(l->size == 0); + free(l); + return EXIT_SUCCESS; +} + +int test_01_list_delete() { + List *l0 = list_create(); + assert(l0); + list_delete(l0, false); + + List *l1 = list_create(); + assert(l1); + for (const int64_t *n = NUMBERS; *n >= 0; n++) { + l1->sentinel.next = node_create((Value)*n, l1->sentinel.next, &l1->sentinel); + l1->size++; + } + list_delete(l1, false); + + List *l2 = list_create(); + assert(l2); + for (const char **s = STRINGS; *s; s++) { + l2->sentinel.next = node_create((Value)strdup(*s), l2->sentinel.next, &l2->sentinel); + l2->size++; + } + list_delete(l2, true); + return EXIT_SUCCESS; +} + +int test_02_list_append() { + List *l1 = list_create(); + assert(l1); + for (size_t i = 0; NUMBERS[i] >= 0; i++) { + list_append(l1, (Value)NUMBERS[i]); + assert(l1->size == (i + 1)); + } + assert(l1->sentinel.next->value.number == NUMBERS[0]); + assert(l1->sentinel.next->next->value.number == NUMBERS[1]); + assert(l1->sentinel.next->next->next->value.number == NUMBERS[2]); + assert(l1->sentinel.prev->value.number == NUMBERS[2]); + assert(l1->sentinel.prev->prev->value.number == NUMBERS[1]); + assert(l1->sentinel.prev->prev->prev->value.number == NUMBERS[0]); + list_delete(l1, false); + + List *l2 = list_create(); + assert(l2); + for (size_t i = 0; STRINGS[i]; i++) { + list_append(l2, (Value)strdup(STRINGS[i])); + assert(l2->size == (i + 1)); + } + assert(strcmp(l2->sentinel.next->value.string , STRINGS[0]) == 0); + assert(strcmp(l2->sentinel.next->next->value.string , STRINGS[1]) == 0); + assert(strcmp(l2->sentinel.next->next->next->value.string, STRINGS[2]) == 0); + assert(strcmp(l2->sentinel.prev->value.string , STRINGS[2]) == 0); + assert(strcmp(l2->sentinel.prev->prev->value.string , STRINGS[1]) == 0); + assert(strcmp(l2->sentinel.prev->prev->prev->value.string, STRINGS[0]) == 0); + list_delete(l2, true); + return EXIT_SUCCESS; +} + +int test_03_list_pop() { + List *l1 = list_create(); + assert(l1); + for (size_t i = 0; NUMBERS[i] >= 0; i++) { + list_append(l1, (Value)NUMBERS[i]); + assert(l1->size == (i + 1)); + } + + Value v1 = list_pop(l1, 1); + assert(v1.number == NUMBERS[1]); + assert(l1->sentinel.next->value.number == NUMBERS[0]); + assert(l1->sentinel.next->next->value.number == NUMBERS[2]); + assert(l1->sentinel.prev->value.number == NUMBERS[2]); + assert(l1->sentinel.prev->prev->value.number == NUMBERS[0]); + assert(l1->size == 2); + + Value v2 = list_pop(l1, 1); + assert(v2.number == NUMBERS[2]); + assert(l1->sentinel.next->value.number == NUMBERS[0]); + assert(l1->sentinel.prev->value.number == NUMBERS[0]); + assert(l1->size == 1); + + Value vX= list_pop(l1, 1); + assert(vX.number == -1L); + + Value v0 = list_pop(l1, 0); + assert(v0.number == NUMBERS[0]); + assert(l1->size == 0); + + list_delete(l1, false); + return EXIT_SUCCESS; +} + +/* Main Execution */ + +int main(int argc, char *argv[]) { + if (argc != 2) { + fprintf(stderr, "Usage: %s NUMBER\n\n", argv[0]); + fprintf(stderr, "Where NUMBER is right of the following:\n"); + fprintf(stderr, " 0 Test list_create\n"); + fprintf(stderr, " 1 Test list_delete\n"); + fprintf(stderr, " 2 Test list_append\n"); + fprintf(stderr, " 3 Test list_pop\n"); + return EXIT_FAILURE; + } + + int number = atoi(argv[1]); + int status = EXIT_FAILURE; + + switch (number) { + case 0: status = test_00_list_create(); break; + case 1: status = test_01_list_delete(); break; + case 2: status = test_02_list_append(); break; + case 3: status = test_03_list_pop(); break; + default: fprintf(stderr, "Unknown NUMBER: %d\n", number); break; + } + + return status; +} + +/* vim: set sts=4 sw=4 ts=8 expandtab ft=c: */ diff --git a/homework07/node.c b/homework07/node.c new file mode 100644 index 0000000..bbcc8d2 --- /dev/null +++ b/homework07/node.c @@ -0,0 +1,31 @@ +/* node.c: Node Structure */ + +#include "list.h" + +/* Node Functions */ + +/** + * Create a Node structure. + * + * @param v Value (Number or String). + * @param next Pointer to next Node structure. + * @param prev Pointer to previous Node structure. + * + * @return Pointer to new Node structure (must be deleted later). + **/ +Node * node_create(Value v, Node *next, Node *prev) { + // TODO + return NULL; +} + +/** + * Delete Node structure and its contents. + * + * @param n Pointer to Node structure. + * @param release Whether or not to free the string value. + **/ +void node_delete(Node *n, bool release) { + // TODO +} + +/* vim: set sts=4 sw=4 ts=8 expandtab ft=c: */ diff --git a/homework07/node.unit.c b/homework07/node.unit.c new file mode 100644 index 0000000..7f0bfcc --- /dev/null +++ b/homework07/node.unit.c @@ -0,0 +1,83 @@ +/* node.unit.c: Node Structure Unit Test */ + +#include "list.h" + +#include +#include +#include +#include +#include + +/* Tests */ + +int test_00_node_create() { + Value v0 = {.number = 42}; + Node *n0 = node_create(v0, NULL, NULL); + assert(n0); + assert(n0->value.number == v0.number); + assert(n0->next == NULL); + assert(n0->prev == NULL); + + Value v1 = {.string = "better now"}; + Node *n1 = node_create(v1, n0, NULL); + assert(n1); + assert(n1->value.string == v1.string); + assert(n1->next == n0); + assert(n1->prev == NULL); + + Node *n2 = node_create((Value)strdup(v1.string), n0, n1); + assert(n2); + assert(strcmp(n2->value.string, v1.string) == 0); + assert(n2->next == n0); + assert(n2->prev == n1); + + free(n0); + free(n1); + free(n2->value.string); + free(n2); + return EXIT_SUCCESS; +} + +int test_01_node_delete() { + Value v0 = {.number = 42}; + Node *n0 = node_create(v0, NULL, NULL); + assert(n0); + + Value v1 = {.string = "better now"}; + Node *n1 = node_create(v1, n0, NULL); + assert(n1); + + Node *n2 = node_create((Value)strdup(v1.string), n0, n1); + assert(n2); + + node_delete(n0, false); + node_delete(n1, false); + node_delete(n2, true); + + return EXIT_SUCCESS; +} + +/* Main Execution */ + +int main(int argc, char *argv[]) { + if (argc != 2) { + fprintf(stderr, "Usage: %s NUMBER\n\n", argv[0]); + fprintf(stderr, "Where NUMBER is right of the following:\n"); + fprintf(stderr, " 0 Test node_create\n"); + fprintf(stderr, " 1 Test node_delete\n"); + return EXIT_FAILURE; + } + + int number = atoi(argv[1]); + int status = EXIT_FAILURE; + + switch (number) { + case 0: status = test_00_node_create(); break; + case 1: status = test_01_node_delete(); break; + default: fprintf(stderr, "Unknown NUMBER: %d\n", number); break; + } + + return status; +} + +/* vim: set sts=4 sw=4 ts=8 expandtab ft=c: */ diff --git a/homework07/seqit.c b/homework07/seqit.c new file mode 100644 index 0000000..4842f3f --- /dev/null +++ b/homework07/seqit.c @@ -0,0 +1,34 @@ +/* seqit.c: Print a sequence of numbers */ + +#include "list.h" + +#include +#include +#include + +/* Functions */ + +void usage(int status) { + fprintf(stderr, "Usage: seqit LAST\n"); + fprintf(stderr, " seqit FIRST LAST\n"); + fprintf(stderr, " seqit FIRST INCREMENT LAST\n"); + exit(status); +} + +List *generate_sequence(ssize_t first, ssize_t increment, ssize_t last) { + // TODO + return NULL; +} + +/* Main Execution */ + +int main(int argc, char *argv[]) { + // TODO: Parse command line arguments + + // TODO: Generate sequence + + // TODO: Print out sequence + return EXIT_SUCCESS; +} + +/* vim: set sts=4 sw=4 ts=8 expandtab ft=c: */ diff --git a/homework07/tailit.c b/homework07/tailit.c new file mode 100644 index 0000000..59cc4de --- /dev/null +++ b/homework07/tailit.c @@ -0,0 +1,34 @@ +/* tailit.c: Output the last part of files */ + +#include "list.h" + +#include +#include +#include +#include + +/* Functions */ + +void usage(int status) { + fprintf(stderr, "Usage: tailit [-n NUMBER]\n\n"); + fprintf(stderr, " -n NUMBER Output the last NUMBER of lines (default is 10)\n"); + exit(status); +} + +List *tail_stream(FILE *stream, size_t limit) { + // TODO + return NULL; +} + +/* Main Execution */ + +int main(int argc, char *argv[]) { + // TODO: Parse command line arguments + + // TODO: Construct tail of stream + + // TODO: Print out tail + return EXIT_SUCCESS; +} + +/* vim: set sts=4 sw=4 ts=8 expandtab ft=c: */