Menu
Coddy logo textTech

Generischer Wrapper

Teil des Abschnitts Objektorientierte Programmierung der C-Journey von Coddy. Lektion 50 von 61.

Ein void* allein kann beliebige Daten speichern, weist jedoch einen entscheidenden Mangel auf: Du verlierst den Überblick darüber, welchen Typ es enthält. Um wirklich nützliche generische Container zu erstellen, müssen wir den Datenzeiger mit Typinformationen verknüpfen. Hier kommt das Muster des generischen Wrappers ins Spiel.

Die Idee ist einfach: Erstelle eine Struktur, die einen void* mit einem Enum bündelt, das den gespeicherten Typ identifiziert. Auf diese Weise weiß der Wrapper immer, wie er seinen Inhalt interpretieren soll.

typedef enum {
    TYPE_INT,
    TYPE_STRING
} DataType;

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

Beim Speichern von Daten reservierst du Speicher für den tatsächlichen Wert und erfasst seinen Typ. Beim Abrufen prüfst du den Typ vor der Typumwandlung:

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

Dieses Muster bildet die Grundlage für die Erstellung typsicherer generischer Container in C. Das enum fungiert als Laufzeittyp-Tag und ermöglicht es deinem Code, sichere Entscheidungen darüber zu treffen, wie die gespeicherten Daten verarbeitet werden.

challenge icon

Aufgabe

Einfach

Erstelle ein typsicheres generisches Wrapper-System, das entweder eine Ganzzahl oder eine Zeichenkette speichern kann und dabei den enthaltenen Typ erfasst, damit wir die Daten später sicher abrufen und ausgeben können.

Du organisierst deinen Code über drei Dateien:

  • wrapper.h: Definiere ein DataType-Enum mit den Werten TYPE_INT und TYPE_STRING. Definiere anschließend eine Wrapper-Struktur, die einen void*-Datenzeiger mit einem DataType-Feld bündelt. Deklariere die Funktionsprototypen zum Erstellen von Wrappern und zum Ausgeben ihres Inhalts.
  • wrapper.c: Implementiere die Wrapper-Funktionalität:
    • wrap_int: nimmt eine Ganzzahl entgegen, reserviert dafür Speicher, speichert den Wert und gibt einen Wrapper mit dem entsprechenden Typ-Tag zurück
    • wrap_string: nimmt eine Zeichenkette (char*) entgegen, reserviert Speicher, kopiert die Zeichenkette und gibt einen Wrapper mit dem Typ-Tag für Zeichenketten zurück
    • print_wrapper: überprüft das Typ-Tag und gibt die Daten entsprechend aus (Ganzzahl unverändert, Zeichenkette unverändert)
    • free_wrapper: gibt die dynamisch reservierten Daten innerhalb des Wrappers frei
  • main.c: Führe alles zusammen. Lies eine Typangabe (i für Ganzzahl, s für Zeichenkette), gefolgt vom Wert. Erstelle den entsprechenden Wrapper, gib seinen Inhalt aus und gib den Speicher frei.

Dein Programm erhält zwei Eingaben:

  1. Eine Typangabe: i für Ganzzahl oder s für Zeichenkette
  2. Der zu verpackende Wert

Beispielausgabe bei den Eingaben i und 42:

42

Beispielausgabe bei den Eingaben s und Hello:

Hello

Beispielausgabe bei den Eingaben i und -100:

-100

Beispielausgabe bei den Eingaben s und Generic Programming:

Generic Programming

Denke daran, Include-Guards in deiner Header-Datei zu verwenden. Reserviere zum Kopieren von Zeichenketten mithilfe von strlen und strcpy genügend Speicherplatz für die Zeichenkette plus den Nullterminator.

Probier es selbst

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

int main() {
    char type;
    scanf("%c", &type);
    getchar(); // Zeilenumbruch verbrauchen
    
    Wrapper w;
    
    if (type == 'i') {
        int value;
        scanf("%d", &value);
        // TODO: Erstelle einen Integer-Wrapper mit wrap_int
        
    } else if (type == 's') {
        char str[256];
        fgets(str, sizeof(str), stdin);
        // Entferne abschließenden Zeilenumbruch, falls vorhanden
        str[strcspn(str, "\n")] = '\0';
        // TODO: Erstelle einen String-Wrapper mit wrap_string
        
    }
    
    // TODO: Gib den Wrapper-Inhalt mit print_wrapper aus
    
    // TODO: Gib den Wrapper-Speicher mit free_wrapper frei
    
    return 0;
}
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung

Übe selbstständig: Online-C-Compiler