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
- Quien llama nunca ve el struct, solo el handle y las funciones.
- Cada operación devuelve un código de error con nombre.
- Los asserts del final son la suite de pruebas del propio módulo.
Palabras clave y builtins usados aquí
NULLcharconstenumforifintreturnsize_tsizeofstaticstructtypedefvoidwhile
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.
Paso 2 de 2 en Bis; paso 11 de 11 en APIs, errores y pruebas.