Les structures permettent de regrouper des attributs hétérogènes pour bâtir des modèles de données complets. Cette section met en pratique les concepts de la Partie 5 à travers trois applications d'ingénierie logicielle : le système de gestion des dossiers étudiants, un module de géométrie 2D et le tri d'un tableau d'entités par classement de mérite.
Problème 1 : Gestionnaire de dossiers académiques#
Énoncé#
Dans le cadre de notre projet fil conducteur, concevez une application modulaire pour gérer la promotion d'étudiants :
1. Définissez un type Etudiant comportant :
- Un identifiant entier (id).
- Le nom et le prénom de l'étudiant.
- Un tableau de 3 notes d'évaluations continues.
- La moyenne générale calculée.
2. Implémentez les fonctions :
- void CalculerMoyenne(Etudiant *e) : calcule et enregistre la moyenne dans le champ correspondant.
- void AfficherEtudiant(const Etudiant *e) : affiche la fiche formatée.
- int TrouverIndiceMajor(const Etudiant promo[], int taille) : renvoie l'indice de l'étudiant ayant la plus haute moyenne.
Solution complète en C#
#include <stdio.h>
#include <string.h>
#define NB_EVALS 3
#define PROMO_SIZE 3
typedef struct
{
int id;
char nom[30];
char prenom[30];
float notes[NB_EVALS];
float moyenne;
} Etudiant;
/* Calcule la moyenne des 3 notes et met à jour la structure */
void CalculerMoyenne(Etudiant *e)
{
float somme = 0.0f;
for (int i = 0; i < NB_EVALS; i++)
{
somme += e->notes[i];
}
e->moyenne = somme / (float)NB_EVALS;
}
/* Affiche une ligne récapitulative formatée */
void AfficherEtudiant(const Etudiant *e)
{
printf("#%04d | %-12s %-12s | Notes: [ ", e->id, e->nom, e->prenom);
for (int i = 0; i < NB_EVALS; i++)
{
printf("%.2f ", e->notes[i]);
}
printf("] | Moyenne: %5.2f/20\n", e->moyenne);
}
/* Renvoie l'indice de l'étudiant ayant la plus forte moyenne */
int TrouverIndiceMajor(const Etudiant promo[], int taille)
{
int indiceMajor = 0;
for (int i = 1; i < taille; i++)
{
if (promo[i].moyenne > promo[indiceMajor].moyenne)
{
indiceMajor = i;
}
}
return indiceMajor;
}
int main(void)
{
Etudiant promotion[PROMO_SIZE] = {
{1001, "Konka", "Joseph", {16.0f, 18.5f, 17.0f}, 0.0f},
{1002, "Traore", "Aminata", {14.0f, 15.0f, 16.5f}, 0.0f},
{1003, "Dubois", "Lucas", {11.0f, 13.0f, 12.0f}, 0.0f}
};
printf("=========================================================================\n");
printf(" GESTION DES DOSSIERS ETUDIANTS \n");
printf("=========================================================================\n");
// Calcul des moyennes pour tous les étudiants
for (int i = 0; i < PROMO_SIZE; i++)
{
CalculerMoyenne(&promotion[i]);
AfficherEtudiant(&promotion[i]);
}
int idxMajor = TrouverIndiceMajor(promotion, PROMO_SIZE);
printf("-------------------------------------------------------------------------\n");
printf("MAJOR DE PROMOTION : %s %s avec %.2f/20 !\n",
promotion[idxMajor].prenom, promotion[idxMajor].nom, promotion[idxMajor].moyenne);
printf("=========================================================================\n");
return 0;
}
Problème 2 : Géométrie 2D avec structures imbriquées#
Énoncé#
- Définissez une structure
Point2Davec coordonnées \(x\) et \(y\) réelles. - Définissez une structure
Cerclecomprenant un pointcentre(structure imbriquée) et un réelrayon. - Écrivez les fonctions :
double CalculerDistance(Point2D p1, Point2D p2): calcule la distance euclidienne \(\sqrt{(x_2-x_1)^2 + (y_2-y_1)^2}\).bool EstDansCercle(Point2D p, Cercle c): vérifie si le point \(p\) se trouve à l'intérieur du disque du cercle \(c\) (\(\text{distance}(p, \text{centre}) \le \text{rayon}\)).
Solution complète en C#
#include <stdio.h>
#include <stdbool.h>
#include <math.h>
typedef struct
{
double x;
double y;
} Point2D;
typedef struct
{
Point2D centre; // Structure imbriquée
double rayon;
} Cercle;
double CalculerDistance(Point2D p1, Point2D p2)
{
double dx = p2.x - p1.x;
double dy = p2.y - p1.y;
return sqrt(dx * dx + dy * dy);
}
bool EstDansCercle(Point2D p, Cercle c)
{
double d = CalculerDistance(p, c.centre);
return (d <= c.rayon);
}
int main(void)
{
Cercle radar = { {0.0, 0.0}, 10.0 }; // Centre en (0,0), rayon = 10
Point2D cible1 = {3.0, 4.0}; // Distance = sqrt(9 + 16) = 5 <= 10
Point2D cible2 = {8.0, 8.0}; // Distance = sqrt(64 + 64) = 11.31 > 10
printf("Radar : Centre (%.1f, %.1f) | Portee : %.1f km\n",
radar.centre.x, radar.centre.y, radar.rayon);
printf("Cible 1 (%.1f, %.1f) dans la zone ? %s\n",
cible1.x, cible1.y, EstDansCercle(cible1, radar) ? "OUI (Detectee)" : "NON");
printf("Cible 2 (%.1f, %.1f) dans la zone ? %s\n",
cible2.x, cible2.y, EstDansCercle(cible2, radar) ? "OUI (Detectee)" : "NON (Hors portee)");
return 0;
}
Problème 3 : Tri d'un tableau d'entités par classement de mérite#
Énoncé#
Implémentez un algorithme qui prend un tableau d'étudiants et les trie par ordre décroissant de leur moyenne générale (du premier au dernier), en déplaçant les structures entières.
Solution complète en C#
#include <stdio.h>
typedef struct
{
int id;
char nom[20];
float moyenne;
} Candidat;
void TrierParMerite(Candidat promo[], int taille)
{
for (int i = 0; i < taille - 1; i++)
{
for (int j = 0; j < taille - 1 - i; j++)
{
// Tri décroissant (> pour les meilleures notes en premier)
if (promo[j].moyenne < promo[j + 1].moyenne)
{
// Échange direct des deux structures complètes !
Candidat temporaire = promo[j];
promo[j] = promo[j + 1];
promo[j + 1] = temporaire;
}
}
}
}
int main(void)
{
Candidat liste[] = {
{101, "Thomas", 13.5f},
{102, "Sarah", 18.0f},
{103, "Karim", 16.25f},
{104, "Chloe", 11.0f}
};
int n = sizeof(liste) / sizeof(liste[0]);
printf("--- CLASSEMENT AVANT TRI ---\n");
for (int i = 0; i < n; i++) printf("%s : %.2f\n", liste[i].nom, liste[i].moyenne);
TrierParMerite(liste, n);
printf("\n--- PALMARES PAR ORDRE DE MERITE ---\n");
for (int i = 0; i < n; i++)
{
printf("Rang %d : %-10s avec %5.2f/20\n", i + 1, liste[i].nom, liste[i].moyenne);
}
return 0;
}
Vous maîtrisez la structuration de données complexes. Dans la Partie 6, nous allons approfondir la manipulation textuelle avec les chaînes de caractères et la bibliothèque <string.h>.
Commentaires