Menu
Coddy logo textTech

Generisches Swap

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

Eine häufige Operation in der Programmierung ist das Vertauschen zweier Werte. Normalerweise würdest du für jeden Typ eine eigene Tauschfunktion schreiben: eine für int, eine andere für double und so weiter. Mit void* und memcpy können wir jedoch eine einzige Funktion schreiben, die zwei beliebige Variablen vertauscht.

Die wichtigste Erkenntnis ist, dass das Austauschen lediglich das Verschieben von Bytes ist. Wenn du die Größe der Daten kennst, kannst du Bytes kopieren, ohne den tatsächlichen Typ zu kennen. Die Funktionssignatur sieht folgendermaßen aus:

void generic_swap(void* a, void* b, size_t size);

Der Parameter size teilt der Funktion mit, wie viele Bytes verschoben werden sollen. Im Inneren verwenden wir einen temporären Puffer und memcpy aus <string.h>, um die Bytes zu vertauschen:

void generic_swap(void* a, void* b, size_t size) {
    char temp[size];      // temporärer Puffer
    memcpy(temp, a, size);  // temp = a
    memcpy(a, b, size);     // a = b
    memcpy(b, temp, size);  // b = temp
}

Jetzt funktioniert diese einzelne Funktion für jeden Typ:

int x = 5, y = 10;
generic_swap(&x, &y, sizeof(int));
// x ist jetzt 10, y ist jetzt 5
double p = 3.14, q = 2.71;
generic_swap(&p, &q, sizeof(double));
// p ist jetzt 2.71, q ist jetzt 3.14

Dieses Muster, bei dem void* mit size_t verwendet wird, ist die Vorgehensweise, mit der die Standardbibliothek von C generische Funktionen wie qsort und bsearch implementiert.

challenge icon

Aufgabe

Einfach

Erstellen wir ein generisches Dienstprogramm zum Tauschen, das die Werte beliebiger zweier Variablen unabhängig von ihrem Typ austauschen kann: mithilfe der Leistungsfähigkeit von void*-Zeigern und memcpy.

Du wirst deinen Code auf drei Dateien verteilen:

  • swap.h: Deklariere deine generic_swap-Funktion, die zwei void*-Zeiger und einen size_t-Parameter entgegennimmt, der die Größe der zu tauschenden Daten angibt. Vergiss die Include-Guards nicht!
  • swap.c: Implementiere die generic_swap-Funktion. Verwende einen temporären Puffer und memcpy, um Bytes zwischen den beiden Speicherstellen zu verschieben. Denke an das Drei-Schritte-Muster zum Tauschen: den ersten Wert in die temporäre Variable kopieren, den zweiten in den ersten kopieren, die temporäre Variable in den zweiten kopieren.
  • main.c: Zeige, dass dein generisches Tauschen mit verschiedenen Datentypen funktioniert. Lies einen Typindikator (i für Ganzzahlen, d für Gleitkommazahlen), gefolgt von zwei Werten. Erstelle zwei Variablen des passenden Typs, tausche sie mithilfe deiner generic_swap-Funktion und gib anschließend beide Werte nach dem Tausch aus.

Dein Programm erhält drei Eingaben:

  1. Einen Typindikator: i für Ganzzahlen oder d für Gleitkommazahlen
  2. Den ersten Wert
  3. Den zweiten Wert

Gib nach dem Tausch beide Werte in separaten Zeilen aus. Verwende für Gleitkommazahlen 2 Nachkommastellen.

Beispielausgabe, wenn die Eingaben i, 5 und 10 sind:

10
5

Beispielausgabe, wenn die Eingaben d, 3.14 und 2.71 sind:

2.71
3.14

Beispielausgabe, wenn die Eingaben i, -7 und 42 sind:

42
-7

Beispielausgabe, wenn die Eingaben d, 99.99 und 0.01 sind:

0.01
99.99

Das Schöne an diesem Ansatz ist, dass deine generic_swap-Funktion keine Ahnung hat, welche Typen sie tauscht. Sie verschiebt lediglich Bytes. Dieselbe Funktion funktioniert für Ganzzahlen, Gleitkommazahlen, Strukturen oder jeden anderen Datentyp. Du musst <string.h> für memcpy und <stddef.h> oder <stdlib.h> für size_t einbinden.

Probier es selbst

#include <stdio.h>
#include "swap.h"

int main() {
    char type;
    scanf("%c", &type);
    
    if (type == 'i') {
        int a, b;
        scanf("%d", &a);
        scanf("%d", &b);
        
        // TODO: Rufe generic_swap auf, um a und b zu tauschen
        // Hinweis: Verwende &a, &b und sizeof(int)
        
        printf("%d\n", a);
        printf("%d\n", b);
    } else if (type == 'd') {
        double a, b;
        scanf("%lf", &a);
        scanf("%lf", &b);
        
        // TODO: Rufe generic_swap auf, um a und b zu tauschen
        // Hinweis: Verwende &a, &b und sizeof(double)
        
        printf("%.2f\n", a);
        printf("%.2f\n", b);
    }
    
    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