diff --git a/stack/.gitignore b/stack/.gitignore new file mode 100644 index 0000000..378eac2 --- /dev/null +++ b/stack/.gitignore @@ -0,0 +1 @@ +build diff --git a/stack/CMakeLists.txt b/stack/CMakeLists.txt new file mode 100755 index 0000000..1c5a6af --- /dev/null +++ b/stack/CMakeLists.txt @@ -0,0 +1,20 @@ +cmake_minimum_required(VERSION 2.6) +project(STACK_TESTS C) + +include_directories(${STACK_TESTS_SOURCE_DIR}/include) + +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Werror") +SET(CMAKE_C_FLAGS_DEBUG "-DDEBUG -g3 -ggdb3") + +SET(CMAKE_SYSTEM_NAME Linux) +SET(CMAKE_SYSTEM_VERSION 1) + +add_library(stack STATIC stack.c) + +add_executable(stack-test stack-test.c stack) + +INSTALL(TARGETS stack + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib +) diff --git a/stack/Makefile b/stack/Makefile new file mode 100755 index 0000000..310469f --- /dev/null +++ b/stack/Makefile @@ -0,0 +1,7 @@ +all: + @rm -rf build; mkdir -p build + cd build; cmake ../ + cd build; make + ./build/stack-test + +.PHONY: all diff --git a/stack/README.md b/stack/README.md new file mode 100755 index 0000000..2b2bda7 --- /dev/null +++ b/stack/README.md @@ -0,0 +1,31 @@ +Stack (vanilla C) +=== + +Implement `stack.c` with the following methods (as defined in `include/stack.h`) + + * create + * push + * pop + * peek + * length + * destroy + +The underlying implementation may be + + * dynamically-sized array + * linked-list + * any other ordered data structure + +The storage strategy may + + * make copies of the original elements + * store pointers to the original elements + +The implementation must pass the following test suite `queue-test.c` + + tar xf stack.tar.gz ~/ + cd ~/stack + mkdir build + cd build + cmake ../ + ./stack-test diff --git a/stack/include/stack.h b/stack/include/stack.h new file mode 100755 index 0000000..987ce1e --- /dev/null +++ b/stack/include/stack.h @@ -0,0 +1,20 @@ +// the implementation of the stack +struct Stack; + +// allocate memory and initialize values +struct Stack* s_create(); + +// return the current length of the stack +int s_length(struct Stack* s); + +// return the new length of the stack +int s_push(struct Stack* s, void* v); + +// pop off the top of the stack ( +void* s_pop(struct Stack* s); + +// look at the most recently inserted element +void* s_peek(struct Stack* s); + +// release the memory allocated +void s_destroy(struct Stack* s); diff --git a/stack/stack-test.c b/stack/stack-test.c new file mode 100755 index 0000000..6125f0a --- /dev/null +++ b/stack/stack-test.c @@ -0,0 +1,151 @@ +#include // puts +#include // exit, EXIT_FAILURE, EXIT_SUCCESS +#include // strcmp + +#include "stack.h" // s_create, s_length, s_push, s_pop, s_peek, s_destroy + +void fail(char* msg) { + puts(msg); + exit(EXIT_FAILURE); +} + +int main(int argc, char* argv[]) { + char* a = "abc"; + char* d = "def"; + char* g = "ghijklmnopqrstuvwxyz"; + + int len = 0; + struct Stack* s = NULL; + + + // + // Test initialized condition + // + if (!(s = s_create())) { + fail("stack did not init properly"); + } + + if (0 != s_length(s)) { + fail("stack is not length 0 after init"); + } + + if (NULL != (char*) s_peek(s)) { + fail("empty stack should peek a NULL pointer"); + } + + if (NULL != s_pop(s)) { + fail("empty stack should pop a NULL pointer"); + } + + + // + // Test edge case of just 1 element + // + if (1 != s_push(s, (void*) a)) { + fail("stack length is not 1"); + } + + if (1 != s_length(s)) { + fail("stack is not length 1 after adding 1 item"); + } + + if (0 != strcmp(a, (char*) s_peek(s))) { + fail("stack item 1 doesn't match peek"); + } + + + // + // Test that stack can hold any number of elements + // + len = 1; + while (len < 99) { + len += 1; + + if (len != s_push(s, (void*) d)) { + fail("len doesn't match expected after push"); + } + + if (len != s_length(s)) { + fail("stack is not the correct length"); + } + + if (0 != strcmp(d, (char*) s_peek(s))) { + fail("item inserted doesn't match peek"); + } + } + + + // + // Test edge case of last element inserted and removed + // + if (100 != s_push(s, (void*) g)) { + fail("stack length is not 100"); + } + + if (100 != s_length(s)) { + fail("stack is not length 100 after adding 100 items"); + } + + if (0 != strcmp(g, (char*) s_peek(s))) { + fail("stack item 100 doesn't match peek"); + } + + if (0 != strcmp(g, (char*) s_pop(s))) { + fail("stack item 1 doesn't match peek"); + } + + if (99 != s_length(s)) { + fail("stack is not length 99 after removing 1 item"); + } + + + // + // Test that the stack can be emptied as it was filled + // + len = 99; + while (len > 1) { + len -= 1; + + if (0 != strcmp(d, (char*) s_peek(s))) { + fail("item peek doesn't match expected"); + } + + if (0 != strcmp(d, (char*) s_pop(s))) { + fail("removed item doesn't match expected value"); + } + + if (len != s_length(s)) { + fail("stack is not the correct length"); + } + } + + + // + // Test edge case of removing first item + // + if (0 != strcmp(a, (char*) s_pop(s))) { + fail("stack item 1 doesn't match pop"); + } + + if (0 != s_length(s)) { + fail("stack is not length 0 after removing all items"); + } + + if (NULL != (char*) s_peek(s)) { + fail("emptied stack should peek a NULL pointer"); + } + + if (NULL != s_pop(s)) { + fail("emptied stack should pop a NULL pointer"); + } + + + // + // Test destruction + // + s_destroy(s); + s = NULL; + + puts("ALL TESTS PASSED!"); + return EXIT_SUCCESS; +} diff --git a/stack/stack.c b/stack/stack.c new file mode 100644 index 0000000..d9fd333 --- /dev/null +++ b/stack/stack.c @@ -0,0 +1,29 @@ +#include // NULL +#include "stack.h" + +struct Stack { + int length; +}; + +struct Stack* s_create() { + return NULL; +} + +int s_push(struct Stack* s, void* v) { + return 0; +} + +int s_length(struct Stack* s) { + return 0; +} + +void* s_pop(struct Stack* s) { + return NULL; +} + +void* s_peek(struct Stack* s) { + return NULL; +} + +void s_destroy(struct Stack* s) { +}