Menu
Coddy logo textTech

Wrapper genérico

Parte de la sección Programación Orientada a Objetos del Journey de C de Coddy. Lección 50 de 61.

Un void* por sí solo puede almacenar cualquier dato, pero tiene un defecto crítico: pierdes la noción del tipo que contiene. Para construir contenedores genéricos realmente útiles, necesitamos asociar el puntero a los datos con información de tipo. Aquí es donde entra en juego el patrón de envoltorio genérico.

La idea es simple: crear un struct que agrupe un void* con un enum que identifique el tipo almacenado. De esta manera, el envoltorio siempre sabe cómo interpretar sus contents.

typedef enum {
    TYPE_INT,
    TYPE_STRING
} DataType;

typedef struct {
    void* data;
    DataType type;
} Wrapper;

Al almacenar datos, asignas memoria para el valor real y registras su tipo. Al recuperarlos, compruebas el tipo antes de realizar la conversión:

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);
    }
}

Este patrón es la base para crear contenedores genéricos con seguridad de tipos en C. El enum actúa como una etiqueta de tipo en tiempo de ejecución, lo que permite que tu código tome decisiones seguras sobre cómo manejar los datos almacenados.

challenge icon

Desafío

Fácil

Construyamos un sistema de wrappers genérico y seguro respecto a los tipos que pueda almacenar un integer o un string, manteniendo un registro del tipo que contiene para que podamos recuperar e imprimir los data de forma segura más adelante.

Organizarás tu código en tres archivos:

  • wrapper.h: Define un DataType enum con los valores TYPE_INT y TYPE_STRING. Después define una estructura Wrapper que agrupe un void* data pointer con un DataType field. Declara los function prototypes para crear wrappers e imprimir sus contents.
  • wrapper.c: Implementa la funcionalidad del wrapper:
    • wrap_int: recibe un integer, asigna memory para él, almacena el valor y devuelve un Wrapper con la etiqueta de tipo apropiada
    • wrap_string: recibe un string (char*), asigna memory y copia el string, y devuelve un Wrapper con la etiqueta de tipo string
    • print_wrapper: comprueba la etiqueta de tipo e imprime los data de forma apropiada (integer tal cual, string tal cual)
    • free_wrapper: libera los data asignados dinámicamente dentro del wrapper
  • main.c: Reúne todo. Lee un indicador de tipo (i para integer, s para string) seguido del valor. Crea el wrapper apropiado, imprime sus contents y libera la memory.

Tu programa recibirá dos entradas:

  1. Un indicador de tipo: i para integer o s para string
  2. El valor que se envolverá

Salida de ejemplo cuando las entradas son i y 42:

42

Salida de ejemplo cuando las entradas son s y Hello:

Hello

Salida de ejemplo cuando las entradas son i y -100:

-100

Salida de ejemplo cuando las entradas son s y Generic Programming:

Generic Programming

Recuerda usar include guards en tu archivo de encabezado. Para copiar strings, asigna suficiente espacio para el string más el terminador null usando strlen y strcpy.

Pruébalo tú mismo

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

int main() {
    char type;
    scanf("%c", &type);
    getchar(); // consumir el salto de línea
    
    Wrapper w;
    
    if (type == 'i') {
        int value;
        scanf("%d", &value);
        // TODO: Crear un wrapper de entero usando wrap_int
        
    } else if (type == 's') {
        char str[256];
        fgets(str, sizeof(str), stdin);
        // Eliminar el salto de línea final si está presente
        str[strcspn(str, "\n")] = '\0';
        // TODO: Crear un wrapper de cadena usando wrap_string
        
    }
    
    // TODO: Imprimir el contenido del wrapper usando print_wrapper
    
    // TODO: Liberar la memoria del wrapper usando free_wrapper
    
    return 0;
}
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación Orientada a Objetos

Practica por tu cuenta: Compilador de C online