From bdfb9c9d57bd3401196d76c96cdbc522d7b6e4c6 Mon Sep 17 00:00:00 2001 From: Andrew Lalis Date: Tue, 23 May 2017 10:45:31 +0200 Subject: [PATCH] Added true generic typing for stacks. Allowed the user to custom define types for stacks, and more to come in the future. --- README.md | 11 ++++- source/handyalgs.h | 111 ----------------------------------------- source/handystack.h | 117 ++++++++++++++++++++++++++++++++++++++++++++ source/templates.h | 7 +++ test.c | 26 +++------- 5 files changed, 142 insertions(+), 130 deletions(-) create mode 100644 source/handystack.h create mode 100644 source/templates.h diff --git a/README.md b/README.md index f2f74b7..dfb9d7a 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,16 @@ A handy collection of C algorithms compiled into one header file for use anywher ## Functionality ### Stack -The stack is probably the most basic storage structure, using the 'first-in, first-out' approach. The following functions are the only ones available for stack manipulation, as it is quite a minimalistic data structure. The STACK_TYPE is a constant defined above the stack functions which can be set by the user to determine the type of items in the stack. By default it is left as an integer. +The stack is probably the most basic storage structure, using the 'first-in, +first-out' approach. To define a stack, the user must first know what type the stack +is, either a primitive type, or a **struct**. To define a stack, you must first define +the **STACK_TYPE** to *int*, *float*, *char*, or whatever type you wish. Then, include +the *handystack* header file. +``` #define STACK_TYPE int + #include "handystack.h" ``` +To define more than one stack, **STACK_TYPE** must first be undefined. +``` #undef STACK_TYPE ``` +Then you simply define the type, and include the header again. Do not try to define two of the same type, however, as that will give all sorts of nasty errors. * ``` Stack createStack() ``` * ``` void freeStack(Stack *s) ``` * ``` void pushToStack(STACK_TYPE item, Stack *s) ``` diff --git a/source/handyalgs.h b/source/handyalgs.h index 3362490..584477f 100644 --- a/source/handyalgs.h +++ b/source/handyalgs.h @@ -10,116 +10,5 @@ Please contact the author regarding bugs and/or feature requests. #ifndef HANDYALGS_H #define HANDYALGS_H -#include -#include -#include - -/* -STACK - The stack is a data structure in which items are stored and retrieved by the first-in, first-out basis. The stack keeps track of the index of the top item, so that the item may be taken out with pop. push will add an item to the top of the list, and increment the top variable. -*/ - -/* -Stack constants: -*/ -// Size allocated to the stack on creation. -#define STACK_SIZE_DEFAULT 8 -// Type to be used for the stack. -#define STACK_TYPE TEST - -/* -Stack Structure: - Stores the top index of the stack, and a list of items in the stack. - top: index of the top of the stack (one above top item). - size: allocated size of the stack's list. - items: list of items in the stack. -*/ -typedef struct { - int top; - int size; - STACK_TYPE* items; -} Stack; - -/* -Stack Functions: -*/ -Stack newStack(); -void freeStack(Stack *s); -void pushToStack(STACK_TYPE item, Stack *s); -STACK_TYPE popFromStack(Stack *s); -void printStack(Stack s); - -/* -Stack Creation: - Creates a new stack with a default size defined above. -*/ -Stack newStack(){ - Stack s; - s.top = 0; - s.size = STACK_SIZE_DEFAULT; - s.items = malloc(s.size*sizeof(STACK_TYPE)); - assert(s.items != NULL); - return s; -} - -/* -Stack Deallocation: - Safely deallocates memory assigned to the stack's list. -*/ -void freeStack(Stack *s){ - free(s->items); -} - -/* -Stack Push: - Pushes an item onto a stack. If there is no more room, more memory will be allocated to accommodate the extra item. -*/ -void pushToStack(STACK_TYPE item, Stack *s){ - //It is safe to push to the stack. - if (s->top < s->size){ - s->items[s->top] = item; - } else { - //There was not enough space, so we must double size. - s->size *= 2; - s->items = realloc(s->items, s->size*sizeof(STACK_TYPE)); - assert(s->items != NULL); - s->items[s->top] = item; - } - s->top++; -} - -/* -Stack Pop: - Pops an item from the top of the stack, if it exists. Size will be checked to see if it is needed to reduce the size of the array. -*/ -STACK_TYPE popFromStack(Stack *s){ - STACK_TYPE result; - //Check if at least one item exists in the list. - if (s->top > 0){ - s->top--; - result = s->items[s->top]; - } else { - //The stack is empty. - fprintf(stderr, "Stack empty, exiting."); - exit(-1); - } - //Check if the items array size can be reduced. - if (s->top < (s->size / 2) && (s->size > STACK_SIZE_DEFAULT)){ - s->size /= 2; - s->items = realloc(s->items, s->size*sizeof(STACK_TYPE)); - assert(s->items != NULL); - } - return result; -} - -/* -Stack Print: - Utility function to print a stack. -*/ -void printStack(Stack s){ - printf("\tStack: \tItems: %d, Allocated Size: %d, Bytes used: %lu\n", s.top, s.size, s.size*sizeof(STACK_TYPE)); -} - - #endif diff --git a/source/handystack.h b/source/handystack.h new file mode 100644 index 0000000..8bc259b --- /dev/null +++ b/source/handystack.h @@ -0,0 +1,117 @@ +/* +handystack.h +Created By: + Andrew Lalis (andrewlalisofficial@gmail.com) + 22 May 2017 +This file is free to use, as long as the above comment remains in the file. +Please contact the author regarding bugs and/or feature requests. +*/ + +#ifdef STACK_TYPE + +#include "templates.h" + +#include +#include +#include + +/* +Stack + The stack is a data structure in which items are stored and retrieved by the first-in, first-out basis. The stack keeps track of the index of the top item, so that the item may be taken out with pop. push will add an item to the top of the list, and increment the top variable. +*/ + +/* +Stack constants: +*/ +// Size allocated to the stack on creation. +#ifndef STACK_SIZE_DEFAULT +#define STACK_SIZE_DEFAULT 8 +#endif + +#define STACK_CONTAINER TEMPLATE(STACK_TYPE, stack) + +/* +Stack Structure: + Stores the top index of the stack, and a list of items in the stack. + top: index of the top of the stack (one above top item). + size: allocated size of the stack's list. + items: list of items in the stack. +*/ +typedef struct { + int top; + int size; + STACK_TYPE* items; +} STACK_CONTAINER; + +/* +Stack Creation: + Creates a new stack with a default size defined above. +*/ +STACK_CONTAINER TEMPLATE(new,STACK_CONTAINER)(){ + STACK_CONTAINER s; + s.top = 0; + s.size = STACK_SIZE_DEFAULT; + s.items = malloc(s.size*sizeof(STACK_TYPE)); + assert(s.items != NULL); + return s; +} + +/* +Stack Deallocation: + Safely deallocates memory assigned to the stack's list. +*/ +void TEMPLATE(free,STACK_CONTAINER)(STACK_CONTAINER *s){ + free(s->items); +} + +/* +Stack Push: + Pushes an item onto a stack. If there is no more room, more memory will be allocated to accommodate the extra item. +*/ +void TEMPLATE(push,STACK_CONTAINER)(STACK_TYPE item, STACK_CONTAINER *s){ + //It is safe to push to the stack. + if (s->top < s->size){ + s->items[s->top] = item; + } else { + //There was not enough space, so we must double size. + s->size *= 2; + s->items = realloc(s->items, s->size*sizeof(STACK_TYPE)); + assert(s->items != NULL); + s->items[s->top] = item; + } + s->top++; +} + +/* +Stack Pop: + Pops an item from the top of the stack, if it exists. Size will be checked to see if it is needed to reduce the size of the array. +*/ +STACK_TYPE TEMPLATE(pop,STACK_CONTAINER)(STACK_CONTAINER *s){ + STACK_TYPE result; + //Check if at least one item exists in the list. + if (s->top > 0){ + s->top--; + result = s->items[s->top]; + } else { + //The stack is empty. + fprintf(stderr, "Stack empty, exiting."); + exit(-1); + } + //Check if the items array size can be reduced. + if (s->top < (s->size / 2) && (s->size > STACK_SIZE_DEFAULT)){ + s->size /= 2; + s->items = realloc(s->items, s->size*sizeof(STACK_TYPE)); + assert(s->items != NULL); + } + return result; +} + +/* +Stack Print: + Utility function to print a stack. +*/ +void TEMPLATE(print,STACK_CONTAINER)(STACK_CONTAINER s){ + printf("\tStack: \tItems: %d, Allocated Size: %d, Bytes used: %lu\n", s.top, s.size, s.size*sizeof(STACK_TYPE)); +} + +#endif \ No newline at end of file diff --git a/source/templates.h b/source/templates.h new file mode 100644 index 0000000..7948f89 --- /dev/null +++ b/source/templates.h @@ -0,0 +1,7 @@ +#ifndef TEMPLATES_H +#define TEMPLATES_H + +#define CONCAT(X,Y) X##_##Y +#define TEMPLATE(X,Y) CONCAT(X,Y) + +#endif \ No newline at end of file diff --git a/test.c b/test.c index d2e152d..b16bab3 100644 --- a/test.c +++ b/test.c @@ -1,22 +1,12 @@ -typedef struct{ - char c; - int v; -} TEST; - -#include "source/handyalgs.h" - #include +#include +#include int main(int argc, char* argv[]){ - Stack s = newStack(); - for (int i = 2; i < 500; i+=3){ - TEST t; - t.v = i; - pushToStack(t, &s); - } - printStack(s); - for (int i = 0; i < 100; i++){ - popFromStack(&s); - } - printStack(s); + + #define STACK_TYPE double + #include "source/handystack.h" + double_stack s = new_double_stack(); + print_double_stack(s); + }