adt_stack.c in C
An abstract data type done properly: opaque handle, error enum, tests in main.
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct Stack Stack;
typedef enum {
STACK_OK = 0,
STACK_EMPTY,
STACK_FULL,
STACK_NULL,
STACK_COUNT
} StackError;
struct Stack {
int *items;
size_t len;
size_t cap;
};
static const char *messages[STACK_COUNT] = {"ok", "stack is empty",
"stack is full", "null handle"};
const char *stack_error(StackError e) {
return (e >= 0 && e < STACK_COUNT) ? messages[e] : "unknown";
}
Stack *stack_new(size_t cap) {
Stack *s = malloc(sizeof *s);
if (s == NULL) {
return NULL;
}
s->items = malloc(cap * sizeof(int));
if (s->items == NULL) {
free(s);
return NULL;
}
s->len = 0;
s->cap = cap;
return s;
}
StackError stack_push(Stack *s, int value) {
if (s == NULL) {
return STACK_NULL;
}
if (s->len == s->cap) {
return STACK_FULL;
}
s->items[s->len++] = value;
return STACK_OK;
}
StackError stack_pop(Stack *s, int *out) {
if (s == NULL || out == NULL) {
return STACK_NULL;
}
if (s->len == 0) {
return STACK_EMPTY;
}
*out = s->items[--s->len];
return STACK_OK;
}
size_t stack_depth(const Stack *s) {
return (s == NULL) ? 0 : s->len;
}
void stack_free(Stack *s) {
if (s == NULL) {
return;
}
free(s->items);
free(s);
}
int main(void) {
Stack *s = stack_new(3);
if (s == NULL) {
fprintf(stderr, "out of memory\n");
return 1;
}
for (int i = 1; i <= 4; i++) {
StackError e = stack_push(s, i * 10);
printf("push %d -> %s\n", i * 10, stack_error(e));
}
assert(stack_depth(s) == 3);
int value = 0;
while (stack_pop(s, &value) == STACK_OK) {
printf("popped %d\n", value);
}
assert(stack_depth(s) == 0);
printf("empty pop -> %s\n", stack_error(stack_pop(s, &value)));
stack_free(s);
printf("all assertions held\n");
return 0;
}
How it works
- Callers never see the struct, only the handle and the functions.
- Every operation returns a named error code.
- The asserts at the end are the module's own test suite.
Keywords and builtins used here
NULLStackcharconstenumforifintmainreturnsize_tsizeofstack_depthstack_errorstack_freestack_newstack_popstack_pushstaticstructtypedefvoidwhile
The run, in numbers
- Lines
- 100
- Characters to type
- 1681
- Tokens
- 544
- Three-star pace
- 110 tpm
At the three-star pace of 110 tokens a minute, this run takes about 297 seconds.
Step 2 of 2 in Encore, step 11 of 11 in APIs, errors & testing.