Menu
Coddy logo textTech

Échange générique

Fait partie de la section Object Oriented Programming du Journey C de Coddy — leçon 51 sur 61.

Une opération courante en programmation consiste à échanger deux valeurs. Normalement, vous devriez écrire une fonction d'échange distincte pour chaque type — une pour int, une autre pour double, et ainsi de suite. Mais avec void* et memcpy, nous pouvons écrire une seule fonction qui échange n'importe quelles deux variables.

L'idée clé est que l'échange consiste simplement à déplacer des octets. Si vous connaissez la taille des données, vous pouvez copier des octets sans connaître le type réel. La signature de la fonction ressemble à ceci :

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

Le paramètre size indique à la fonction combien d'octets déplacer. À l'intérieur, nous utilisons un tampon temporaire et memcpy de <string.h> pour déplacer les octets :

void generic_swap(void* a, void* b, size_t size) {
    char temp[size];      // tampon temporaire
    memcpy(temp, a, size);  // temp = a
    memcpy(a, b, size);     // a = b
    memcpy(b, temp, size);  // b = temp
}

Désormais, cette fonction unique fonctionne pour n'importe quel type :

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

Ce modèle — l'utilisation de void* avec size_t — est la manière dont la bibliothèque standard du C implémente des fonctions génériques comme qsort et bsearch.

challenge icon

Défi

Facile

Construisons un utilitaire d'échange générique capable d'échanger les valeurs de n'importe quelles deux variables, quel que soit leur type — en utilisant la puissance des pointeurs void* et de memcpy.

Vous organiserez votre code sur trois fichiers :

  • swap.h : Déclarez votre fonction generic_swap qui prend deux pointeurs void* et un paramètre size_t indiquant la taille des données à échanger. N'oubliez pas les gardes d'inclusion !
  • swap.c : Implémentez la fonction generic_swap. Utilisez un tampon temporaire et memcpy pour déplacer les octets entre les deux emplacements mémoire. Rappelez-vous le modèle d'échange en trois étapes : copier la première valeur vers le tampon temporaire, copier la seconde vers la première, copier le tampon temporaire vers la seconde.
  • main.c : Démontrez le fonctionnement de votre échange générique avec différents types de données. Lisez un indicateur de type (i pour les entiers, d pour les doubles) suivi de deux valeurs. Créez deux variables du type approprié, échangez-les à l'aide de votre fonction generic_swap, puis affichez les deux valeurs après l'échange.

Votre programme recevra trois entrées :

  1. Un indicateur de type : i pour un entier ou d pour un double
  2. La première valeur
  3. La deuxième valeur

Après l'échange, affichez les deux valeurs sur des lignes séparées. Pour les doubles, utilisez 2 décimales.

Exemple de sortie lorsque les entrées sont i, 5, et 10 :

10
5

Exemple de sortie lorsque les entrées sont d, 3.14, et 2.71 :

2.71
3.14

Exemple de sortie lorsque les entrées sont i, -7, et 42 :

42
-7

Exemple de sortie lorsque les entrées sont d, 99.99, et 0.01 :

0.01
99.99

La beauté de cette approche est que votre fonction generic_swap n'a aucune idée des types qu'elle échange — elle déplace simplement des octets. La même fonction fonctionne pour les entiers, les doubles, les structures ou tout autre type de données. Vous devrez inclure <string.h> pour memcpy et <stddef.h> ou <stdlib.h> pour size_t.

Aide-mémoire

Une fonction d'échange générique utilise des pointeurs void* et memcpy pour échanger les valeurs de n'importe quel type en déplaçant des octets sans connaître le type réel.

Signature de la fonction :

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

Implémentation utilisant un tampon temporaire et memcpy :

void generic_swap(void* a, void* b, size_t size) {
    char temp[size];      // tampon temporaire
    memcpy(temp, a, size);  // temp = a
    memcpy(a, b, size);     // a = b
    memcpy(b, temp, size);  // b = temp
}

Utilisation avec différents types :

int x = 5, y = 10;
generic_swap(&x, &y, sizeof(int));
// x vaut maintenant 10, y vaut maintenant 5

double p = 3.14, q = 2.71;
generic_swap(&p, &q, sizeof(double));
// p vaut maintenant 2.71, q vaut maintenant 3.14

En-têtes requis : <string.h> pour memcpy et <stddef.h> ou <stdlib.h> pour size_t.

Essayez vous-même

#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: Appeler generic_swap pour échanger a et b
        // Astuce : Utiliser &a, &b, et sizeof(int)
        
        printf("%d\n", a);
        printf("%d\n", b);
    } else if (type == 'd') {
        double a, b;
        scanf("%lf", &a);
        scanf("%lf", &b);
        
        // TODO: Appeler generic_swap pour échanger a et b
        // Astuce : Utiliser &a, &b, et sizeof(double)
        
        printf("%.2f\n", a);
        printf("%.2f\n", b);
    }
    
    return 0;
}
quiz iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Object Oriented Programming