finish Q32

This commit is contained in:
feng-arch 2024-12-18 17:15:11 +08:00
parent cfe99c1caa
commit eacf46ec84
22 changed files with 524 additions and 0 deletions

5
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,5 @@
{
"files.associations": {
"assert.h": "c"
}
}

View File

@ -0,0 +1,6 @@
CFALGS=-wall -g
all: ex3
clean:
rm -rf ./ex3
ex3:
cc ex3.c -o ex3

View File

View File

@ -0,0 +1,60 @@
CFLAGS=-g -O2 -Wall -Wextra -Isrc -rdynamic -DNDEBUG $(OPTFLAGS)
LIBS=-ldl $(OPTLIBS)
PREFIX?=/usr/local
SOURCES=$(wildcard src/**/*.c src/*.c)
OBJECTS=$(patsubst %.c,%.o,$(SOURCES))
TEST_SRC=$(wildcard tests/*_tests.c)
TESTS=$(patsubst %.c,%,$(TEST_SRC))
TARGET=build/libYOUR_LIBRARY.a
SO_TARGET=$(patsubst %.a,%.so,$(TARGET))
# The Target Build
all: $(TARGET) $(SO_TARGET) tests
dev: CFLAGS=-g -Wall -Isrc -Wall -Wextra $(OPTFLAGS)
dev: all
$(TARGET): CFLAGS += -fPIC
$(TARGET): build $(OBJECTS)
ar rcs $@ $(OBJECTS)
ranlib $@
$(SO_TARGET): $(TARGET) $(OBJECTS)
$(CC) -shared -o $@ $(OBJECTS)
build:
@mkdir -p build
@mkdir -p bin
# The Unit Tests
.PHONY: tests
$(TESTS): %: %.c $(TARGET)
$(CC) $(CFLAGS) $< -o $@ $(TARGET) $(LIBS)
tests: $(TESTS)
sh ./tests/runtests.sh
valgrind:
VALGRIND="valgrind --log-file=/tmp/valgrind-%p.log" $(MAKE)
# The Cleaner
clean:
rm -rf build $(OBJECTS) $(TESTS)
rm -f tests/tests.log
find . -name "*.gc*" -exec rm {} \;
rm -rf `find . -name "*.dSYM" -print`
# The Install
install: all
install -d $(DESTDIR)/$(PREFIX)/lib/
install $(TARGET) $(DESTDIR)/$(PREFIX)/lib/
# The Checker
BADFUNCS='[^_.>a-zA-Z0-9](str(n?cpy|n?cat|xfrm|n?dup|str|pbrk|tok|_)|stpn?cpy|a?sn?printf|byte_)'
check:
@echo Files with potentially dangerous functions.
@egrep $(BADFUNCS) $(SOURCES) || true

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,45 @@
#ifndef _dbg_h_
#define _dbg_h_
#include <stdio.h>
#include <errno.h>
#include <string.h>
#ifdef NDEBUG
#define debug(M, ...)
#else
#define debug(M, ...) fprintf(stderr, "DEBUG %s:%d:" M "\n", __FILE__, __LINE__, ##__VA_ARGS__)
#endif
#define clean_errno() (errno == 0 ? "None" : strerror(errno))
#define log_err(M, ...) fprintf(stderr, "[ERROR] (%s:%d: errno: %s) " M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__)
#define log_warn(M, ...) fprintf(stderr, "[WARN] (%s:%d: errno: %s) " M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__)
#define log_info(M, ...) fprintf(stderr, "[INFO] (%s:%d) " M "\n", __FILE__, __LINE__, ##__VA_ARGS__)
#define check(A, M, ...) \
if (!(A)) \
{ \
log_err(M, ##__VA_ARGS__); \
errno = 0; \
goto error; \
}
#define sentinel(M, ...) \
{ \
log_err(M, ##__VA_ARGS__); \
errno = 0; \
goto error; \
}
#define check_mem(A) check((A), "Out of memory.")
#define check_debug(A, M, ...) \
if (!(A)) \
{ \
debug(M, ##__VA_ARGS__); \
errno = 0; \
goto error; \
}
#endif

View File

@ -0,0 +1,125 @@
#include "list.h"
#include "dbg.h"
List *List_create()
{
return calloc(1, sizeof(List));
}
void List_destroy(List *list)
{
LIST_FOREACH(list, first, next, cur)
{
if (cur->prev)
{
free(cur->prev);
}
}
free(list->last);
free(list);
}
void List_clear_destroy(List *list)
{
List_clear(list);
List_destroy(list);
}
void List_clear(List *list)
{
LIST_FOREACH(list, first, next, cur)
{
free(cur->value);
}
}
void List_push(List *list, void *value)
{
ListNode *node = calloc(1, sizeof(ListNode));
check_mem(node);
node->value = value;
if (list->last == NULL)
{
list->first = node;
list->last = node;
}
else
{
list->last->next = node;
node->prev = list->last;
list->last = node;
}
list->count++;
error:
return;
}
void *List_pop(List *list)
{
ListNode *node = list->last;
return node != NULL ? List_remove(list, node) : NULL;
}
void List_unshift(List *list, void *value)
{
ListNode *node = calloc(1, sizeof(ListNode));
check_mem(node);
node->value = value;
if (list->first == NULL)
{
list->first = node;
list->last = node;
}
else
{
node->next = list->first;
list->first->prev = node;
list->first = node;
}
list->count++;
error:
return;
}
void *List_shift(List *list)
{
ListNode *node = list->first;
return node != NULL ? List_remove(list, node) : NULL;
}
void *List_remove(List *list, ListNode *node)
{
void *result = NULL;
check(list->first && list->last, "List is empty.");
check(node, "node can't be NULL");
if (node == list->first && node == list->last)
{
list->first = NULL;
list->last = NULL;
}
else if (node == list->first)
{
list->first = node->next;
check(list->first != NULL, "Invalid list, somehow got a first that is NULL.");
list->first->prev = NULL;
}
else if (node == list->last)
{
list->last = node->prev;
check(list->last != NULL, "Invalid list, somehow got a next that is NULL.");
list->last->next = NULL;
}
else
{
ListNode *after = node->next;
ListNode *before = node->prev;
before->next = after;
after->prev = before;
}
list->count--;
result = node->value;
free(node);
error:
return result;
}

View File

@ -0,0 +1,41 @@
#ifndef lcthw_List_h
#define lcthw_List_h
#include <stdlib.h>
typedef struct ListNode
{
struct ListNode *next;
struct ListNode *prev;
void *value;
} ListNode;
typedef struct List
{
int count;
ListNode *first;
ListNode *last;
} List;
List *List_create();
void List_destroy(List *list);
void List_clear(List *list);
void List_clear_destroy(List *list);
#define List_count(A) ((A)->count)
#define List_first(A) (((A)->first != NULL) ? ((A)->first->value) : NULL)
#define List_last(A) ((A)->last != NULL ? (A)->last->value : NULL)
void List_push(List *list, void *value);
void *List_pop(List *list);
void List_unshift(List *list, void *value);
void *List_shift(List *list);
void *List_remove(List *list, ListNode *node);
#define LIST_FOREACH(L, S, M, V) \
ListNode *_node = NULL; \
ListNode *V = NULL; \
for (V = _node = L->S; _node != NULL; V = _node = _node->M)
#endif

Binary file not shown.

View File

@ -0,0 +1,45 @@
#ifndef _dbg_h_
#define _dbg_h_
#include <stdio.h>
#include <errno.h>
#include <string.h>
#ifdef NDEBUG
#define debug(M, ...)
#else
#define debug(M, ...) fprintf(stderr, "DEBUG %s:%d:" M "\n", __FILE__, __LINE__, ##__VA_ARGS__)
#endif
#define clean_errno() (errno == 0 ? "None" : strerror(errno))
#define log_err(M, ...) fprintf(stderr, "[ERROR] (%s:%d: errno: %s) " M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__)
#define log_warn(M, ...) fprintf(stderr, "[WARN] (%s:%d: errno: %s) " M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__)
#define log_info(M, ...) fprintf(stderr, "[INFO] (%s:%d) " M "\n", __FILE__, __LINE__, ##__VA_ARGS__)
#define check(A, M, ...) \
if (!(A)) \
{ \
log_err(M, ##__VA_ARGS__); \
errno = 0; \
goto error; \
}
#define sentinel(M, ...) \
{ \
log_err(M, ##__VA_ARGS__); \
errno = 0; \
goto error; \
}
#define check_mem(A) check((A), "Out of memory.")
#define check_debug(A, M, ...) \
if (!(A)) \
{ \
debug(M, ##__VA_ARGS__); \
errno = 0; \
goto error; \
}
#endif

Binary file not shown.

View File

@ -0,0 +1,107 @@
#include "minunit.h"
#include <lcthw/list.h>
#include <assert.h>
static List *list = NULL;
char *test1 = "test1 data";
char *test2 = "test2 data";
char *test3 = "test3 data";
char *test_create()
{
list = List_create();
mu_assert(list != NULL, "Failed to create list.");
return NULL;
}
char *test_destroy()
{
List_clear_destroy(list);
return NULL;
}
char *test_push_pop()
{
List_push(list, test1);
mu_assert(List_last(list) == test1, "Wrong last value.");
List_push(list, test2);
mu_assert(List_last(list) == test2, "Wrong last value");
List_push(list, test3);
mu_assert(List_last(list) == test3, "Wrong last value.");
mu_assert(List_count(list) == 3, "Wrong count on push.");
char *val = List_pop(list);
mu_assert(val == test3, "Wrong value on pop.");
val = List_pop(list);
mu_assert(val == test2, "Wrong value on pop.");
val = List_pop(list);
mu_assert(val == test1, "Wrong value on pop.");
mu_assert(List_count(list) == 0, "Wrong count after pop.");
return NULL;
}
char *test_unshift()
{
List_unshift(list, test1);
mu_assert(List_first(list) == test1, "Wrong first value.");
List_unshift(list, test2);
mu_assert(List_first(list) == test2, "Wrong first value");
List_unshift(list, test3);
mu_assert(List_first(list) == test3, "Wrong last value.");
mu_assert(List_count(list) == 3, "Wrong count on unshift.");
return NULL;
}
char *test_remove()
{
// we only need to test the middle remove case since push/shift
// already tests the other cases
char *val = List_remove(list, list->first->next);
mu_assert(val == test2, "Wrong removed element.");
mu_assert(List_count(list) == 2, "Wrong count after remove.");
mu_assert(List_first(list) == test3, "Wrong first after remove.");
mu_assert(List_last(list) == test1, "Wrong last after remove.");
return NULL;
}
char *test_shift()
{
mu_assert(List_count(list) != 0, "Wrong count before shift.");
char *val = List_shift(list);
mu_assert(val == test3, "Wrong value on shift.");
val = List_shift(list);
mu_assert(val == test1, "Wrong value on shift.");
mu_assert(List_count(list) == 0, "Wrong count after shift.");
return NULL;
}
char *all_tests()
{
mu_suite_start();
mu_run_test(test_create);
mu_run_test(test_push_pop);
mu_run_test(test_unshift);
mu_run_test(test_remove);
mu_run_test(test_shift);
mu_run_test(test_destroy);
return NULL;
}
RUN_TESTS(all_tests);

View File

@ -0,0 +1,45 @@
#undef NDEBUG
#ifndef _minunit_h
#define _minunit_h
#include <stdio.h>
#include "dbg.h"
#include <stdlib.h>
#define mu_suite_start() char *message = NULL
#define mu_assert(test, message) \
if (!(test)) \
{ \
log_err(message); \
return message; \
}
#define mu_run_test(test) \
debug("\n-----%s", " " #test); \
message = test(); \
tests_run++; \
if (message) \
return message;
#define RUN_TESTS(name) \
int main(int argc, char *argv[]) \
{ \
(void)argc; \
debug("----- RUNNING: %s", argv[0]); \
printf("----\nRUNNING: %s\n", argv[0]); \
char *result = name(); \
if (result != 0) \
{ \
printf("FAILED: %s\n", result); \
} \
else \
{ \
printf("ALL TESTS PASSED\n"); \
} \
printf("Tests run: %d\n", tests_run); \
exit(result != 0); \
}
int tests_run;
#endif

View File

@ -0,0 +1,4 @@
#!/bin/sh
SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
cd "$SCRIPT_DIR"
./list_tests

View File

@ -0,0 +1,6 @@
CFALGS=-wall -g
all: ex3
clean:
rm -rf ./ex3
ex3:
cc ex3.c -o ex3

BIN
pre-study_phase/2024_12_18/Q4/ex3 Executable file

Binary file not shown.

View File

@ -0,0 +1,8 @@
#include <stdio.h>
int main(){
int age = 10;
int height = 94;
printf("I am %d years old.\n",age);
printf("I am %d inches tall.\n", height);
return 0;
}

View File

@ -0,0 +1,8 @@
CFALGS=-wall -g
all: ex6
ex6: ex6.o
cc ex6.o -o ex6
%.o: %.c
cc -c $< -o $@
clean:
rm -rf *.o ex6

BIN
pre-study_phase/2024_12_18/Q6/ex6 Executable file

Binary file not shown.

View File

@ -0,0 +1,19 @@
#include <stdio.h>
int main(int argc, char *argv[])
{
int distance = 100;
float power = 2.345f;
double super_power = 534265.64357;
char initial = 'A';
char first_name[] = "Zed";
char last_name[] = "Shaw";
printf("You are %d miles away.\n", distance);
printf("You have %f levels of power.\n", power);
printf("You have %f awesome super power.\n", super_power);
printf("I have an initial %c.\n", initial);
printf("I have a first name %s.\n", first_name);
printf("I have a last name %s.\n", last_name);
printf("My whole name is %s %c %s.\n", first_name, initial, last_name);
return 0;
}

Binary file not shown.