typestar

adt_stack.c en C

Un tipo de dato abstracto bien hecho: handle opaco, enum de errores, pruebas en 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;
}

Cómo funciona

  1. Quien llama nunca ve el struct, solo el handle y las funciones.
  2. Cada operación devuelve un código de error con nombre.
  3. Los asserts del final son la suite de pruebas del propio módulo.

Palabras clave y builtins usados aquí

El intento, en números

Líneas
100
Caracteres a escribir
1681
Tokens
544
Ritmo de tres estrellas
110 tpm

Al ritmo de tres estrellas de 110 tokens por minuto, este intento toma unos 297 segundos.

Escribe este fragmento

Paso 2 de 2 en Bis; paso 11 de 11 en APIs, errores y pruebas.

← Anterior