RosettaCodeData/Task/Stack/C/stack-2.c

72 lines
2.2 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdbool.h>
#define check_pointer(p) if (!p) {puts("Out of memory."); exit(EXIT_FAILURE);}
#define MINIMUM_SIZE 1
/* Minimal stack size (expressed in number of elements) for which
space is allocated. It should be at least 1. */
#define GROWTH_FACTOR 2
/* How much more memory is allocated each time a stack grows
out of its allocated segment. */
typedef int T;
// The type of the stack elements.
typedef struct
{T *bottom;
T *top;
T *allocated_top;} stack;
stack * new(void)
/* Creates a new stack. */
{stack *s = malloc(sizeof(stack));
check_pointer(s);
s->bottom = malloc(MINIMUM_SIZE * sizeof(T));
check_pointer(s->bottom);
s->top = s->bottom - 1;
s->allocated_top = s->bottom + MINIMUM_SIZE - 1;
return s;}
void destroy(stack *s)
/* Frees all the memory used for a stack. */
{free(s->bottom);
free(s);}
bool empty(stack *s)
/* Returns true iff there are no elements on the stack. This
is different from the stack not having enough memory reserved
for even one element, which case is never allowed to arise. */
{return s->top < s->bottom ? true : false;}
void push(stack *s, T x)
/* Puts a new element on the stack, enlarging the latter's
memory allowance if necessary. */
{if (s->top == s->allocated_top)
{ptrdiff_t qtty = s->top - s->bottom + 1;
ptrdiff_t new_qtty = GROWTH_FACTOR * qtty;
s->bottom = realloc(s->bottom, new_qtty * sizeof(T));
check_pointer(s->bottom);
s->top = s->bottom + qtty - 1;
s->allocated_top = s->bottom + new_qtty - 1;}
*(++s->top) = x;}
T pop(stack *s)
/* Removes and returns the topmost element. The result of popping
an empty stack is undefined. */
{return *(s->top--);}
void compress(stack *s)
/* Frees any memory the stack isn't actually using. The
allocated portion still isn't allowed to shrink smaller than
MINIMUM_SIZE. If all the stack's memory is in use, nothing
happens. */
{if (s->top == s->allocated_top) return;
ptrdiff_t qtty = s->top - s->bottom + 1;
if (qtty < MINIMUM_SIZE) qtty = MINIMUM_SIZE;
size_t new_size = qtty * sizeof(T);
s->bottom = realloc(s->bottom, new_size);
check_pointer(s->bottom);
s->allocated_top = s->bottom + qtty - 1;}