Menu
Coddy logo textTech

Wrapper generico

Fa parte della sezione Programmazione orientata agli oggetti del percorso C di Coddy. Lezione 50 di 61.

Un void* da solo può memorizzare qualsiasi dato, ma ha un difetto critico: perdi traccia del tipo che contiene. Per creare contenitori generici davvero utili, dobbiamo associare il puntatore ai dati alle informazioni sul tipo. È qui che entra in gioco il pattern Generic Wrapper.

L’idea è semplice: crea una struct che raggruppa un void* con un enum che identifica il tipo memorizzato. In questo modo, il wrapper sa sempre come interpretarne il contenuto.

typedef enum {
    TYPE_INT,
    TYPE_STRING
} DataType;
typedef struct {
    void* data;
    DataType type;
} Wrapper;

Quando memorizzi i dati, allochi memoria per il valore effettivo e ne registri il tipo. Quando li recuperi, controlli il tipo prima di eseguire il cast:

Wrapper wrap_int(int value) {
    int* p = malloc(sizeof(int));
    *p = value;
    return (Wrapper){ .data = p, .type = TYPE_INT };
}
void print_wrapper(Wrapper* w) {
    if (w->type == TYPE_INT) {
        printf("%d\n", *(int*)w->data);
    } else if (w->type == TYPE_STRING) {
        printf("%s\n", (char*)w->data);
    }
}

Questo schema è la base per creare contenitori generici e sicuri rispetto ai tipi in C. L'enum funge da tag di tipo in fase di esecuzione, permettendo al tuo codice di prendere decisioni sicure su come gestire i dati memorizzati.

challenge icon

Sfida

Facile

Creiamo un sistema generico di wrapper type-safe in grado di memorizzare un intero oppure una stringa, tenendo traccia del tipo contenuto così da poter recuperare e stampare i dati in sicurezza in seguito.

Organizzerai il codice in tre file:

  • wrapper.h: Definisci un'enum DataType con i valori TYPE_INT e TYPE_STRING. Poi definisci una struct Wrapper che raggruppi un puntatore ai dati void* con un campo DataType. Dichiara i prototipi delle funzioni per creare i wrapper e stamparne il contenuto.
  • wrapper.c: Implementa le funzionalità del wrapper:
    • wrap_int: accetta un intero, ne alloca la memoria, memorizza il valore e restituisce un Wrapper con il tag del tipo appropriato
    • wrap_string: accetta una stringa (char*), alloca memoria e copia la stringa, quindi restituisce un Wrapper con il tag del tipo stringa
    • print_wrapper: controlla il tag del tipo e stampa i dati nel modo appropriato (l'intero così com'è, la stringa così com'è)
    • free_wrapper: libera i dati allocati dinamicamente all'interno del wrapper
  • main.c: Metti tutto insieme. Leggi un indicatore di tipo (i per l'intero, s per la stringa) seguito dal valore. Crea il wrapper appropriato, stampane il contenuto e libera la memoria.

Il programma riceverà due input:

  1. Un indicatore di tipo: i per un intero oppure s per una stringa
  2. Il valore da racchiudere nel wrapper

Esempio di output quando gli input sono i e 42:

42

Esempio di output quando gli input sono s e Hello:

Hello

Esempio di output quando gli input sono i e -100:

-100

Esempio di output quando gli input sono s e Generic Programming:

Generic Programming

Ricordati di usare le include guard nel file header. Per copiare la stringa, alloca spazio sufficiente per la stringa più il terminatore nullo usando strlen e strcpy.

Provalo tu

#include <stdio.h>
#include <string.h>
#include "wrapper.h"

int main() {
    char type;
    scanf("%c", &type);
    getchar(); // consuma il carattere di nuova riga
    
    Wrapper w;
    
    if (type == 'i') {
        int value;
        scanf("%d", &value);
        // TODO: Crea un wrapper per un intero usando wrap_int
        
    } else if (type == 's') {
        char str[256];
        fgets(str, sizeof(str), stdin);
        // Rimuovi il carattere di nuova riga finale, se presente
        str[strcspn(str, "\n")] = '\0';
        // TODO: Crea un wrapper per una stringa usando wrap_string
        
    }
    
    // TODO: Stampa il contenuto del wrapper usando print_wrapper
    
    // TODO: Libera la memoria del wrapper usando free_wrapper
    
    return 0;
}
quiz iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Programmazione orientata agli oggetti

Esercitati da solo: Compilatore C online