typestar

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

  1. Callers never see the struct, only the handle and the functions.
  2. Every operation returns a named error code.
  3. The asserts at the end are the module's own test suite.

Keywords and builtins used here

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.

Type this snippet

Step 2 of 2 in Encore, step 11 of 11 in APIs, errors & testing.

← Previous