Menu
Coddy logo textTech

Échange générique

Fait partie de la section Programmation Orientée Objet du Journey C de Coddy. Leçon 51 sur 61.

Une opération courante en programmation consiste à échanger deux valeurs. Normalement, tu écrirais une fonction swap 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 deux variables quelconques.

L’idée essentielle 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 se présente ainsi :

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 permuter 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
}

Maintenant, cette fonction unique fonctionne pour n’importe quel type :

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

Ce modèle, qui utilise void* avec size_t, est la manière dont la bibliothèque standard de C implémente des fonctions génériques comme qsort et bsearch.

challenge icon

Défi

Facile

Construisons un utilitaire générique d’échange capable d’échanger les valeurs de deux variables quelconques, 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 accepte 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. Souvenez-vous du modèle d’échange en trois étapes : copier la première valeur dans le tampon temporaire, copier la deuxième dans la première, puis copier le contenu du tampon temporaire dans la deuxième.
  • 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 nombres réels en double précision), 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 nombre réel en double précision
  2. La première valeur
  3. La deuxième valeur

Après l’échange, affichez les deux valeurs sur des lignes distinctes. Pour les nombres réels en double précision, 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 réside dans le fait que votre fonction generic_swap ne sait pas quels types elle échange. Elle ne fait que déplacer des octets. La même fonction fonctionne pour les entiers, les nombres réels en double précision, 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.

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: Appelez generic_swap pour échanger a et b
        // Indice : Utilisez &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: Appelez generic_swap pour échanger a et b
        // Indice : Utilisez &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 Programmation Orientée Objet

Entraînez-vous par vous-même : Compilateur C en ligne