Exercices Langage C

Exercice 2 Langage C Corrigé S1

Gestion d'un Carnet d'Adresses

Objectifs :

  1. Manipuler des structures de données.
  2. Utiliser des tableaux dynamiques et l'allocation dynamique de mémoire.
  3. Rechercher et trier des données.

Énoncé : Écrivez un programme en C pour gérer un carnet d'adresses. Chaque contact dans le carnet d'adresses doit être représenté par une structure contenant les informations suivantes :

  • Nom,
  • Prénom,
  • Numéro de téléphone,
  • Adresse email.

Le programme doit afficher un menu avec les options suivantes :

------------------MENU------------------
1: Ajouter un contact
2: Supprimer un contact
3: Rechercher un contact par nom
4: Trier les contacts par nom
5: Afficher tous les contacts
6: Sauvegarder les contacts dans un fichier
0: Quitter le programme
-----------------------------------------

Détails des options :

  • Ajouter un contact : Demander à l'utilisateur de saisir les informations du contact (nom, prénom, numéro de téléphone et email) et ajouter le contact au carnet.

  • Supprimer un contact : Demander à l'utilisateur de saisir le nom du contact à supprimer. Si le contact existe, il est supprimé.

  • Rechercher un contact par nom : Demander à l'utilisateur de saisir le nom du contact à rechercher, et afficher les informations de ce contact.

  • Trier les contacts par nom : Trier les contacts par ordre alphabétique selon leur nom et afficher la liste triée.

  • Afficher tous les contacts : Afficher tous les contacts avec leurs informations.

  • Sauvegarder les contacts : Sauvegarder tous les contacts dans un fichier texte spécifié par l'utilisateur.

Consignes :

  • Utiliser un tableau dynamique pour stocker les contacts.
  • Gérer la réallocation de la mémoire lors de l'ajout et de la suppression de contacts.
  • Implémenter des algorithmes de tri (comme le tri par sélection ou le tri par insertion) pour trier les contacts.

1. Structure du Contact

Chaque contact est représenté par une structure qui contient les informations suivantes :

typedef struct {
    char nom[50];
    char prenom[50];
    char telephone[20];
    char email[50];
} Contact;

2. Menu principal

Le programme doit offrir un menu pour que l'utilisateur puisse choisir l'action à effectuer. Voici comment cela pourrait être mis en œuvre :

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define TAILLE_INITIALE 2

typedef struct {
    char nom[50];
    char prenom[50];
    char telephone[20];
    char email[50];
} Contact;

void afficher_menu();
void ajouter_contact(Contact** carnet, int* nb_contacts, int* taille_max);
void supprimer_contact(Contact* carnet, int* nb_contacts);
void rechercher_contact(Contact* carnet, int nb_contacts);
void trier_contacts(Contact* carnet, int nb_contacts);
void afficher_contacts(Contact* carnet, int nb_contacts);
void sauvegarder_contacts(Contact* carnet, int nb_contacts);

int main() {
    int choix;
    int nb_contacts = 0;
    int taille_max = TAILLE_INITIALE;
    Contact* carnet = malloc(taille_max * sizeof(Contact));

    if (carnet == NULL) {
        printf("Erreur d'allocation mémoire\n");
        return 1;
    }

    do {
        afficher_menu();
        printf("Choisissez une option: ");
        scanf("%d", &choix);
        getchar();  // Pour éviter les problèmes avec l'entrée du caractère de retour.

        switch (choix) {
            case 1:
                ajouter_contact(&carnet, &nb_contacts, &taille_max);
                break;
            case 2:
                supprimer_contact(carnet, &nb_contacts);
                break;
            case 3:
                rechercher_contact(carnet, nb_contacts);
                break;
            case 4:
                trier_contacts(carnet, nb_contacts);
                break;
            case 5:
                afficher_contacts(carnet, nb_contacts);
                break;
            case 6:
                sauvegarder_contacts(carnet, nb_contacts);
                break;
            case 0:
                printf("Au revoir!\n");
                break;
            default:
                printf("Option invalide\n");
                break;
        }
    } while (choix != 0);

    free(carnet);
    return 0;
}

void afficher_menu() {
    printf("\n------------------MENU------------------\n");
    printf("1: Ajouter un contact\n");
    printf("2: Supprimer un contact\n");
    printf("3: Rechercher un contact par nom\n");
    printf("4: Trier les contacts par nom\n");
    printf("5: Afficher tous les contacts\n");
    printf("6: Sauvegarder les contacts dans un fichier\n");
    printf("0: Quitter le programme\n");
    printf("-----------------------------------------\n");
}

3. Ajouter un contact

Lors de l'ajout d'un contact, si le tableau est plein, nous devons allouer plus d'espace à l'aide de realloc.

void ajouter_contact(Contact** carnet, int* nb_contacts, int* taille_max) {
    if (*nb_contacts == *taille_max) {
        *taille_max *= 2;
        *carnet = realloc(*carnet, *taille_max * sizeof(Contact));
        if (*carnet == NULL) {
            printf("Erreur de réallocation mémoire\n");
            exit(1);
        }
    }

    printf("Nom : ");
    fgets((*carnet)[*nb_contacts].nom, 50, stdin);
    (*carnet)[*nb_contacts].nom[strcspn((*carnet)[*nb_contacts].nom, "\n")] = 0; // Supprimer le '\n'

    printf("Prénom : ");
    fgets((*carnet)[*nb_contacts].prenom, 50, stdin);
    (*carnet)[*nb_contacts].prenom[strcspn((*carnet)[*nb_contacts].prenom, "\n")] = 0;

    printf("Téléphone : ");
    fgets((*carnet)[*nb_contacts].telephone, 20, stdin);
    (*carnet)[*nb_contacts].telephone[strcspn((*carnet)[*nb_contacts].telephone, "\n")] = 0;

    printf("Email : ");
    fgets((*carnet)[*nb_contacts].email, 50, stdin);
    (*carnet)[*nb_contacts].email[strcspn((*carnet)[*nb_contacts].email, "\n")] = 0;

    (*nb_contacts)++;
    printf("Contact ajouté avec succès !\n");
}

4. Supprimer un contact

La suppression d'un contact nécessite de rechercher le contact à supprimer, puis de décaler les autres contacts dans le tableau.

void supprimer_contact(Contact* carnet, int* nb_contacts) {
    char nom[50];
    printf("Nom du contact à supprimer : ");
    fgets(nom, 50, stdin);
    nom[strcspn(nom, "\n")] = 0;

    int trouve = 0;
    for (int i = 0; i < *nb_contacts; i++) {
        if (strcmp(carnet[i].nom, nom) == 0) {
            trouve = 1;
            for (int j = i; j < *nb_contacts - 1; j++) {
                carnet[j] = carnet[j + 1];
            }
            (*nb_contacts)--;
            printf("Contact supprimé avec succès !\n");
            break;
        }
    }

    if (!trouve) {
        printf("Contact non trouvé.\n");
    }
}

5. Rechercher un contact par nom

Pour rechercher un contact, nous parcourons le tableau et comparons les noms.

void rechercher_contact(Contact* carnet, int nb_contacts) {
    char nom[50];
    printf("Nom du contact à rechercher : ");
    fgets(nom, 50, stdin);
    nom[strcspn(nom, "\n")] = 0;

    for (int i = 0; i < nb_contacts; i++) {
        if (strcmp(carnet[i].nom, nom) == 0) {
            printf("Nom : %s\nPrénom : %s\nTéléphone : %s\nEmail : %s\n",
                   carnet[i].nom, carnet[i].prenom, carnet[i].telephone, carnet[i].email);
            return;
        }
    }

    printf("Contact non trouvé.\n");
}

6. Trier les contacts par nom

Le tri par sélection est simple à implémenter et permet de trier les contacts par ordre alphabétique.

void trier_contacts(Contact* carnet, int nb_contacts) {
    for (int i = 0; i < nb_contacts - 1; i++) {
        int min_idx = i;
        for (int j = i + 1; j < nb_contacts; j++) {
            if (strcmp(carnet[j].nom, carnet[min_idx].nom) < 0) {
                min_idx = j;
            }
        }

        if (min_idx != i) {
            Contact temp = carnet[i];
            carnet[i] = carnet[min_idx];
            carnet[min_idx] = temp;
        }
    }

    printf("Contacts triés avec succès.\n");
}

7. Afficher tous les contacts

Cette fonction affiche tous les contacts du carnet.

void afficher_contacts(Contact* carnet, int nb_contacts) {
    if (nb_contacts == 0) {
        printf("Aucun contact à afficher.\n");
    } else {
        for (int i = 0; i < nb_contacts; i++) {
            printf("Nom : %s, Prénom : %s, Téléphone : %s, Email : %s\n",
                   carnet[i].nom, carnet[i].prenom, carnet[i].telephone, carnet[i].email);
        }
    }
}

8. Sauvegarder les contacts dans un fichier

La sauvegarde des contacts dans un fichier texte permet de conserver les données pour une utilisation future.

void sauvegarder_contacts(Contact* carnet, int nb_contacts) {
    char nom_fichier[50];
    printf("Nom du fichier de sauvegarde : ");
    fgets(nom_fichier, 50, stdin);
    nom_fichier[strcspn(nom_fichier, "\n")] = 0;

    FILE* fichier = fopen(nom_fichier, "w");
    if (fichier == NULL) {
        printf("Erreur lors de l'ouverture du fichier.\n");
        return;
    }

    for (int i = 0; i < nb_contacts; i++) {
        fprintf(fichier, "%s,%s,%s,%s\n", carnet[i].nom, carnet[i].prenom, carnet[i].telephone, carnet[i].email);
    }

    fclose(fichier);
    printf("Contacts sauvegardés avec succès dans le fichier %s.\n", nom_fichier);
}

 

Ajouter un commentaire

Veuillez vous connecter pour ajouter un commentaire.

Pas encore de commentaires.