Algorithmique et Structures de Données 2 TP N°3 : LES STRUCTURES

Ce TP porte sur la manipulation des structures en langage C à travers plusieurs exercices pratiques. Il permet d’apprendre à définir des structures complexes, saisir et afficher des données, manipuler des tableaux de structures, et écrire des fonctions pour traiter ces données.

D'après le document Algorithmique et Structures de Données 2 TP N°3 : LES STRUCTURES

Cet article a été rédigé automatiquement à partir du document source, puis vérifié avant publication.

Algorithmique et Structures de Données 2 TP N°3 : LES STRUCTURES

Document source

Algorithmique et Structures de Données 2 TP N°3 : LES STRUCTURES

Programming, Mathematics · PDF · 4 pages · 2019

Afficher l'aperçu du document

Consulter le document original →

Ce TP porte sur la manipulation des structures en langage C à travers plusieurs exercices pratiques. Il permet d’apprendre à définir des structures complexes, saisir et afficher des données, manipuler des tableaux de structures, et écrire des fonctions pour traiter ces données. Pour réaliser ce TP, il est nécessaire de disposer d’un environnement de programmation C fonctionnel et d’une connaissance de base en programmation structurée et en gestion des tableaux.

Objectifs

  • Savoir définir et utiliser des structures en C.
  • Apprendre à saisir, stocker et afficher des données structurées.
  • Manipuler des tableaux de structures et écrire des fonctions de traitement.
  • Mettre en œuvre des contrôles de saisie sur les données.
  • Développer des fonctions récursives pour le traitement de structures.

Prérequis et installation

  • Connaissance de base du langage C (variables, tableaux, fonctions).
  • Compréhension des structures en C.
  • Environnement de développement C (compilateur GCC ou équivalent).
  • Éditeur de texte ou IDE pour écrire le code source.

Exercice 1 : Gestion des joueurs d’une équipe de rugby

Dans cet exercice, vous devez créer un programme C qui mémorise les informations relatives à 15 joueurs d’une équipe de rugby. Chaque joueur est caractérisé par son numéro de poste (de 1 à 15), son nom, son prénom et son poids.

Étape 1 : Écrire une fonction pour remplir un tableau de joueurs.

  • Cette fonction doit saisir pour chaque joueur : numéro de poste, nom, prénom et poids.
  • Effectuer des contrôles de saisie pour le numéro (doit être entre 1 et 15) et le poids (valeurs cohérentes).
  • Une fois le tableau rempli, afficher toutes les informations saisies.
typedef struct {
  int numero;
  char nom[30];
  char prenom[30];
  float poids;
} Joueur;

void remplirJoueurs(Joueur equipe[], int taille) {
  for (int i = 0; i < taille; i++) {
    do {
      printf("Saisir le numéro du joueur %d (1-15) : ", i + 1);
      scanf("%d", &equipe[i].numero);
    } while (equipe[i].numero < 1 || equipe[i].numero > 15);

    printf("Saisir le nom du joueur %d : ", i + 1);
    scanf("%s", equipe[i].nom);

    printf("Saisir le prénom du joueur %d : ", i + 1);
    scanf("%s", equipe[i].prenom);

    do {
      printf("Saisir le poids du joueur %d : ", i + 1);
      scanf("%f", &equipe[i].poids);
    } while (equipe[i].poids <= 0);
  }

  printf("\nInformations des joueurs saisis :\n");
  for (int i = 0; i < taille; i++) {
    printf("Numéro : %d, Nom : %s, Prénom : %s, Poids : %.2f\n",
           equipe[i].numero, equipe[i].nom, equipe[i].prenom, equipe[i].poids);
  }
}

Étape 2 : Écrire une fonction pour afficher le joueur le plus lourd et le poids moyen.

  • Parcourir le tableau pour trouver le joueur avec le poids maximal.
  • Calculer la moyenne des poids de tous les joueurs.
  • Afficher le poids, numéro, nom et prénom du joueur le plus lourd, ainsi que la moyenne.
void afficherPoidsEtMoyenne(Joueur equipe[], int taille) {
  int indicePlusLourd = 0;
  float sommePoids = 0;

  for (int i = 0; i < taille; i++) {
    sommePoids += equipe[i].poids;
    if (equipe[i].poids > equipe[indicePlusLourd].poids) {
      indicePlusLourd = i;
    }
  }

  float poidsMoyen = sommePoids / taille;

  printf("Joueur le plus lourd : %s %s, Numéro : %d, Poids : %.2f\n",
         equipe[indicePlusLourd].prenom, equipe[indicePlusLourd].nom,
         equipe[indicePlusLourd].numero, equipe[indicePlusLourd].poids);

  printf("Poids moyen des joueurs : %.2f\n", poidsMoyen);
}

Exercice 2 : Gestion des participants à des compétitions de tennis

La fédération de tennis souhaite gérer informatiquement les participants aux compétitions. Un participant est défini par son ncin, son nom et son prénom (chacun limité à 20 caractères). Une compétition est définie par un identifiant, un nom (max 10 caractères) et un ensemble de participants (max 50).

Étape 1 : Définir les structures Participant et Competition.

typedef struct {
  int ncin;
  char nom[21];
  char prenom[21];
} Participant;

typedef struct {
  int id;
  char nom_compet[11];
  Participant participants[50];
  int nb_participants;
} Competition;

Étape 2 : Écrire la fonction saisir_participant qui saisit et retourne un participant.

Participant saisir_participant() {
  Participant p;
  printf("Saisir le NCIN du participant : ");
  scanf("%d", &p.ncin);

  printf("Saisir le nom (max 20 caractères) : ");
  scanf("%20s", p.nom);

  printf("Saisir le prénom (max 20 caractères) : ");
  scanf("%20s", p.prenom);

  return p;
}

Étape 3 : Écrire la fonction saisir_competitions qui saisit n compétitions.

void saisir_competitions(Competition S[], int n) {
  for (int i = 0; i < n; i++) {
    printf("Saisir l'identifiant de la compétition %d : ", i + 1);
    scanf("%d", &S[i].id);

    printf("Saisir le nom de la compétition (max 10 caractères) : ");
    scanf("%10s", S[i].nom_compet);

    printf("Saisir le nombre de participants (max 50) : ");
    do {
      scanf("%d", &S[i].nb_participants);
    } while (S[i].nb_participants < 0 || S[i].nb_participants > 50);

    for (int j = 0; j < S[i].nb_participants; j++) {
      printf("Participant %d :\n", j + 1);
      S[i].participants[j] = saisir_participant();
    }
  }
}

Étape 4 : Écrire la fonction nbre_comp qui retourne le nombre de compétitions où un participant donné a participé.

int nbre_comp(Competition S[], int n, int ncin) {
  int compteur = 0;
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < S[i].nb_participants; j++) {
      if (S[i].participants[j].ncin == ncin) {
        compteur++;
        break;
      }
    }
  }
  return compteur;
}

Étape 5 : Écrire le main qui :

  • Saisit le nombre n de compétitions (non négatif).
  • Définit un tableau S13 pour la saison 2013.
  • Saisit les données des n compétitions.
  • Saisit un ncin et affiche le nombre de compétitions auxquelles ce participant a pris part.
int main() {
  int n;
  do {
    printf("Saisir le nombre total de compétitions (non négatif) : ");
    scanf("%d", &n);
  } while (n < 0);

  Competition S13[n];

  saisir_competitions(S13, n);

  int ncin_recherche;
  printf("Saisir le NCIN du participant à rechercher : ");
  scanf("%d", &ncin_recherche);

  int nb = nbre_comp(S13, n, ncin_recherche);
  printf("Le participant avec NCIN %d a participé à %d compétition(s).\n", ncin_recherche, nb);

  return 0;
}

Exercice 3 : Gestion de dates

On considère une structure DATE avec les champs jour, mois et année sous forme de chaînes de caractères.

Étape 1 : Écrire une fonction pour saisir une date avec contrôles.

typedef struct {
  char jour[3];
  char mois[3];
  char annee[5];
} DATE;

void saisir_date(DATE *d) {
  do {
    printf("Saisir le jour (2 caractères) : ");
    scanf("%2s", d->jour);
  } while (/* contrôle valide du jour à implémenter ici */ 0);

  do {
    printf("Saisir le mois (2 caractères) : ");
    scanf("%2s", d->mois);
  } while (/* contrôle valide du mois à implémenter ici */ 0);

  do {
    printf("Saisir l'année (4 caractères) : ");
    scanf("%4s", d->annee);
  } while (/* contrôle valide de l'année à implémenter ici */ 0);
}

Étape 2 : Écrire une fonction qui incrémente une date d un nombre n de jours.

void incrementer_date(DATE *d, int n) {
  // Code pour incrémenter la date d de n jours
  // Cette fonction doit gérer le passage des jours, mois et années
  // Le code exact dépend de la gestion des dates (non précisée ici)
}

Étape 3 : Écrire une fonction pour afficher une date.

void afficher_date(DATE d) {
  printf("Date : %s/%s/%s\n", d.jour, d.mois, d.annee);
}

Étape 4 : Écrire un programme qui saisit une date, l’incrémente et affiche la nouvelle date.

int main() {
  DATE d;
  saisir_date(&d);

  int n;
  printf("Saisir le nombre de jours à ajouter : ");
  scanf("%d", &n);

  incrementer_date(&d, n);
  afficher_date(d);

  return 0;
}

Exercice 4 : Gestion de stock et commandes de produits bureautiques

Ce programme gère un stock de produits bureautiques et les commandes associées.

Étape 1 : Définir la structure article.

typedef struct {
  char modele[21];
  float prix_unitaire;
  int quantite;
} Article;

Étape 2 : Écrire la fonction ajouterArticle qui ajoute un article au tableau stock à une position donnée.

void ajouterArticle(Article stock[], Article a, int position, int *taille) {
  if (position < 0 || position > *taille || *taille >= 100) {
    printf("Position invalide ou stock plein.\n");
    return;
  }
  for (int i = *taille; i > position; i--) {
    stock[i] = stock[i - 1];
  }
  stock[position] = a;
  (*taille)++;
}

Étape 3 : Écrire un programme principal pour remplir le stock avec des articles saisis.

int main() {
  Article stock[100];
  int taille = 0;
  int n;

  printf("Saisir le nombre d'articles à ajouter (max 100) : ");
  scanf("%d", &n);

  for (int i = 0; i < n; i++) {
    Article a;
    printf("Saisir le modèle de l'article %d : ", i + 1);
    scanf("%20s", a.modele);

    printf("Saisir le prix unitaire : ");
    scanf("%f", &a.prix_unitaire);

    printf("Saisir la quantité disponible : ");
    scanf("%d", &a.quantite);

    ajouterArticle(stock, a, taille, &taille);
  }

  printf("Stock initial :\n");
  for (int i = 0; i < taille; i++) {
    printf("Modèle : %s, Prix : %.2f, Quantité : %d\n",
           stock[i].modele, stock[i].prix_unitaire, stock[i].quantite);
  }

  return 0;
}

Étape 4 : Définir les structures commandeUnitaire et commande.

typedef struct {
  char modele[21];
  int quantite;
} commandeUnitaire;

typedef struct {
  char nom_client[50];
  commandeUnitaire commandes[100];
  int nb_commandes;
} commande;

Étape 5 : Écrire une fonction pour saisir un ensemble de commandes unitaires.

void saisir_commandes_unitaires(commandeUnitaire commandes[], int *nb) {
  printf("Saisir le nombre de commandes unitaires : ");
  scanf("%d", nb);

  for (int i = 0; i < *nb; i++) {
    printf("Saisir le modèle du produit %d : ", i + 1);
    scanf("%20s", commandes[i].modele);

    printf("Saisir la quantité demandée : ");
    scanf("%d", &commandes[i].quantite);
  }
}

Étape 6 : Écrire la fonction retirerCommandeUnitaire qui met à jour le stock et retourne le prix ou 0 si impossible.

float retirerCommandeUnitaire(Article stock[], int taille, commandeUnitaire c) {
  for (int i = 0; i < taille; i++) {
    if (strcmp(stock[i].modele, c.modele) == 0) {
      if (stock[i].quantite >= c.quantite) {
        stock[i].quantite -= c.quantite;
        return c.quantite * stock[i].prix_unitaire;
      } else {
        printf("Quantité insuffisante pour le modèle %s.\n", c.modele);
        return 0;
      }
    }
  }
  printf("Produit %s non trouvé dans le stock.\n", c.modele);
  return 0;
}

Étape 7 : Constituer une commande, retirer les articles du stock et afficher le prix total.

int main() {
  Article stock[100];
  int taille = 0;
  // Remplir le stock comme précédemment

  commande c;
  printf("Saisir le nom du client : ");
  scanf("%49s", c.nom_client);

  saisir_commandes_unitaires(c.commandes, &c.nb_commandes);

  float prix_total = 0;
  for (int i = 0; i < c.nb_commandes; i++) {
    float prix = retirerCommandeUnitaire(stock, taille, c.commandes[i]);
    prix_total += prix;
  }

  printf("Prix total de la commande : %.2f\n", prix_total);

  printf("Stock après commande :\n");
  for (int i = 0; i < taille; i++) {
    printf("Modèle : %s, Prix : %.2f, Quantité : %d\n",
           stock[i].modele, stock[i].prix_unitaire, stock[i].quantite);
  }

  return 0;
}

Exercice 5 : Gestion d’un album musical

On considère les structures suivantes :

typedef struct {
  int minutes;
  int secondes;
} Temps;

typedef struct {
  char Titre[30];
  char Interprete[30];
  Temps Duree;
} Chanson;

Étape 1 : Définir le type Album comme un tableau de 1 à 12 chansons.

typedef Chanson Album[12];

Étape 2 : Écrire la fonction void SaisirChanson(Chanson *C) pour saisir une chanson.

void SaisirChanson(Chanson *C) {
  printf("Saisir le titre de la chanson : ");
  scanf("%29s", C->Titre);

  printf("Saisir l'interprète : ");
  scanf("%29s", C->Interprete);

  printf("Saisir la durée (minutes) : ");
  scanf("%d", &C->Duree.minutes);

  printf("Saisir la durée (secondes) : ");
  scanf("%d", &C->Duree.secondes);
}

Étape 3 : Écrire la fonction void AfficherChanson(Chanson C) pour afficher une chanson.

void AfficherChanson(Chanson C) {
  printf("Titre : %s\n", C.Titre);
  printf("Interprète : %s\n", C.Interprete);
  printf("Durée : %d min %d sec\n", C.Duree.minutes, C.Duree.secondes);
}

Étape 4 : Écrire la fonction int ComparerDurees(Chanson C1, Chanson C2) qui compare les durées.

int ComparerDurees(Chanson C1, Chanson C2) {
  int duree1 = C1.Duree.minutes * 60 + C1.Duree.secondes;
  int duree2 = C2.Duree.minutes * 60 + C2.Duree.secondes;

  if (duree1 > duree2) return 1;
  else if (duree1 < duree2) return 2;
  else return 0;
}

Étape 5 : Écrire la fonction RemplirAlbum(Album A, int N) pour remplir un album de N chansons.

void RemplirAlbum(Album A, int N) {
  for (int i = 0; i < N; i++) {
    printf("Saisie de la chanson %d :\n", i + 1);
    SaisirChanson(&A[i]);
  }
}

Étape 6 : Écrire la fonction récursive int ChansonsMemeInterpret(Album A, int N, char[] Intp) qui affiche les chansons d’un interprète et retourne leur nombre.

int ChansonsMemeInterpret(Album A, int N, char Intp[]) {
  if (N == 0) return 0;

  int count = ChansonsMemeInterpret(A, N - 1, Intp);
  if (strcmp(A[N - 1].Interprete, Intp) == 0) {
    AfficherChanson(A[N - 1]);
    return count + 1;
  }
  return count;
}

Étape 7 : Écrire un programme C qui :

  • Remplit un album avec N chansons.
  • Saisit le nom d’un interprète et affiche toutes ses chansons ainsi que leur nombre.
  • Affiche la chanson la plus courte de l’album.
int main() {
  int N;
  Album A;

  do {
    printf("Saisir le nombre de chansons dans l'album (1 à 12) : ");
    scanf("%d", &N);
  } while (N < 1 || N > 12);

  RemplirAlbum(A, N);

  char interprete[30];
  printf("Saisir le nom de l'interprète à rechercher : ");
  scanf("%29s", interprete);

  int nb = ChansonsMemeInterpret(A, N, interprete);
  printf("Nombre de chansons de %s : %d\n", interprete, nb);

  // Recherche de la chanson la plus courte
  int indicePlusCourte = 0;
  int dureeMin = A[0].Duree.minutes * 60 + A[0].Duree.secondes;
  for (int i = 1; i < N; i++) {
    int duree = A[i].Duree.minutes * 60 + A[i].Duree.secondes;
    if (duree < dureeMin) {
      dureeMin = duree;
      indicePlusCourte = i;
    }
  }

  printf("Chanson la plus courte :\n");
  AfficherChanson(A[indicePlusCourte]);

  return 0;
}

Résultats attendus

  • Exercice 1 : Affichage correct des 15 joueurs avec leurs informations, identification du joueur le plus lourd et calcul du poids moyen.
  • Exercice 2 : Saisie des compétitions et participants, calcul correct du nombre de compétitions d’un participant donné.
  • Exercice 3 : Saisie et affichage corrects des dates, incrémentation fonctionnelle de la date.
  • Exercice 4 : Gestion correcte du stock, ajout d’articles, mise à jour des quantités lors des commandes, calcul du prix total.
  • Exercice 5 : Saisie et affichage des chansons, comparaison des durées, affichage des chansons d’un interprète donné, identification de la chanson la plus courte.

Pièges courants

  • Ne pas effectuer les contrôles de saisie sur les numéros, poids, tailles de chaînes ou quantités, ce qui peut provoquer des erreurs ou dépassements.
  • Oublier de gérer la limite maximale des tableaux (ex : 15 joueurs, 50 participants, 100 articles, 12 chansons).
  • Confondre la comparaison de chaînes de caractères avec l’opérateur == au lieu de strcmp.
  • Ne pas initialiser ou mettre à jour correctement les compteurs et indices lors des recherches.
  • Dans la gestion des dates, ne pas gérer correctement les dépassements de jours et mois lors de l’incrémentation.
  • Lors du retrait d’une commande unitaire, ne pas vérifier la disponibilité suffisante du stock avant mise à jour.
  • En saisissant des chaînes, ne pas limiter la taille avec scanf, ce qui peut causer un dépassement de tampon.

Partager

Commentaires

Aucun commentaire pour le moment. Posez la première question.

Les commentaires sont relus avant publication. Votre e-mail n'est jamais affiché.

← Toutes les révisions