Homework 07: Initial Import
This commit is contained in:
parent
1432c00d54
commit
1a1cb9f122
8 changed files with 482 additions and 0 deletions
66
homework07/Makefile
Normal file
66
homework07/Makefile
Normal file
|
|
@ -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
|
||||
50
homework07/list.c
Normal file
50
homework07/list.c
Normal file
|
|
@ -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: */
|
||||
41
homework07/list.h
Normal file
41
homework07/list.h
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
/* list.h: Doubly Linked List Library */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* 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: */
|
||||
143
homework07/list.unit.c
Normal file
143
homework07/list.unit.c
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
/* list.unit.c: List Structure Unit Test */
|
||||
|
||||
#include "list.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* 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: */
|
||||
31
homework07/node.c
Normal file
31
homework07/node.c
Normal file
|
|
@ -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: */
|
||||
83
homework07/node.unit.c
Normal file
83
homework07/node.unit.c
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
/* node.unit.c: Node Structure Unit Test */
|
||||
|
||||
#include "list.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* 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: */
|
||||
34
homework07/seqit.c
Normal file
34
homework07/seqit.c
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
/* seqit.c: Print a sequence of numbers */
|
||||
|
||||
#include "list.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* 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: */
|
||||
34
homework07/tailit.c
Normal file
34
homework07/tailit.c
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
/* tailit.c: Output the last part of files */
|
||||
|
||||
#include "list.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* 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: */
|
||||
Loading…
Reference in a new issue