How to implement a generic stack with void pointers in C

2 Answers

0 votes
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

/* Node for linked-list stack */
typedef struct Node {
    void *data;
    struct Node *next;
} Node;

/* Stack structure */
typedef struct {
    Node *top;
} Stack;

/* Initialize stack */
void stack_init(Stack *s) {
    s->top = NULL;
}

/* Check if empty */
bool stack_empty(Stack *s) {
    return s->top == NULL;
}

/* Push: user must provide a pointer to allocated data */
bool stack_push(Stack *s, void *data) {
    Node *n = malloc(sizeof(Node));
    if (!n)
        return false;

    n->data = data;
    n->next = s->top;
    s->top = n;
    
    return true;
}

/* Pop: returns pointer to data (caller must free it) */
void* stack_pop(Stack *s) {
    if (stack_empty(s))
        return NULL;

    Node *n = s->top;
    void *data = n->data;
    s->top = n->next;
    free(n);
    
    return data;
}

/* Peek: does NOT remove */
void* stack_peek(Stack *s) {
    if (stack_empty(s))
        return NULL;
    return s->top->data;
}

/* Print stack using a user-provided print function */
void stack_print(Stack *s, void (*print_fn)(void*)) {
    printf("Stack (top → bottom): ");
    for (Node *n = s->top; n != NULL; n = n->next)
        print_fn(n->data);
    printf("\n");
}

/* Free all nodes (but NOT the data — user owns it) */
void stack_clear(Stack *s) {
    Node *n = s->top;
    while (n) {
        Node *next = n->next;
        free(n);
        n = next;
    }
    s->top = NULL;
}

/* Example print function for int* */
void print_int(void *p) {
    printf("%d ", *(int*)p);
}

int main(void) {
    Stack s;
    stack_init(&s);

    /* ---- push int ---- */
    int *a = malloc(sizeof(int));
    *a = 42;
    stack_push(&s, a);

    /* ---- push double ---- */
    double *b = malloc(sizeof(double));
    *b = 3.14159;
    stack_push(&s, b);

    /* ---- push string ---- */
    char *c = malloc(20);
    snprintf(c, 20, "hello");
    stack_push(&s, c);

    /* ---- print stack ---- */
    printf("Stack contents:\n");
    Node *n = s.top;
    while (n) {
        /* We must know what type each node holds. */

        /* Example: detect type by comparing pointer sizes */
        if (n->data == a)
            printf("int: %d\n", *(int*)n->data);
        else if (n->data == b)
            printf("double: %.5f\n", *(double*)n->data);
        else if (n->data == c)
            printf("string: %s\n", (char*)n->data);

        n = n->next;
    }

    /* ---- pop and free everything ---- */
    while (!stack_empty(&s)) {
        void *d = stack_pop(&s);
        free(d);
    }

    return 0;
}


/* 
run:

Stack contents:
string: hello
double: 3.14159
int: 42

*/

 



answered 16 minutes ago by avibootz
0 votes
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>

/* ----- Type system ----- */
typedef enum {
    T_INT,
    T_DOUBLE,
    T_STRING
} Type;

typedef struct {
    void *data;
    Type type;
} TypedValue;

/* ----- Node + Stack ----- */
typedef struct Node {
    TypedValue value;
    struct Node *next;
} Node;

typedef struct {
    Node *top;
} Stack;

/* ----- Stack operations ----- */

void stack_init(Stack *s) {
    s->top = NULL;
}

bool stack_empty(Stack *s) {
    return s->top == NULL;
}

/* Push: takes ownership of TypedValue.data */
bool stack_push(Stack *s, TypedValue v) {
    Node *n = malloc(sizeof(Node));
    if (!n)
        return false;

    n->value = v;
    n->next = s->top;
    s->top = n;
    return true;
}

/* Pop: returns TypedValue; caller must free value.data */
TypedValue stack_pop(Stack *s) {
    TypedValue out = { NULL, T_INT };

    if (stack_empty(s))
        return out;

    Node *n = s->top;
    out = n->value;
    s->top = n->next;
    free(n);
    
    return out;
}

TypedValue stack_peek(Stack *s) {
    if (stack_empty(s)) {
        TypedValue empty = { NULL, T_INT };
        return empty;
    }
    
    return s->top->value;
}

/* Print a single TypedValue */
void print_value(TypedValue v) {
    switch (v.type) {
        case T_INT:
            printf("%d ", *(int*)v.data);
            break;
        case T_DOUBLE:
            printf("%.5f ", *(double*)v.data);
            break;
        case T_STRING:
            printf("%s ", (char*)v.data);
            break;
    }
}

/* Print entire stack */
void stack_print(Stack *s) {
    printf("Stack (top → bottom): ");
    for (Node *n = s->top; n != NULL; n = n->next)
        print_value(n->value);
    printf("\n");
}

/* Free all nodes AND their data */
void stack_clear(Stack *s) {
    while (!stack_empty(s)) {
        TypedValue v = stack_pop(s);
        free(v.data);
    }
}

/* ----- main ----- */

int main(void) {
    Stack s;
    stack_init(&s);

    /* Push int */
    int *a = malloc(sizeof(int));
    *a = 42;
    stack_push(&s, (TypedValue){ a, T_INT });

    /* Push double */
    double *b = malloc(sizeof(double));
    *b = 3.14159;
    stack_push(&s, (TypedValue){ b, T_DOUBLE });

    /* Push string */
    char *c = malloc(20);
    snprintf(c, 20, "hello");
    stack_push(&s, (TypedValue){ c, T_STRING });

    stack_print(&s);

    /* Pop one */
    TypedValue v = stack_pop(&s);
    printf("Popped: ");
    print_value(v);
    printf("\n");
    free(v.data);

    stack_print(&s);

    stack_clear(&s);
    
    return 0;
}



/* 
run:

Stack (top → bottom): hello 3.14159 42 
Popped: hello 
Stack (top → bottom): 3.14159 42 

*/

 



answered 4 minutes ago by avibootz
...