Gestion robuste de données étudiantes avec C++ : flux et gestion d'erreurs

Traitement des données de compétition

Implémentation d'une structure Competiteur avec opérateurs spécialisés pour les opérations d'entrée/sortie :

#pragma once
#include <iomanip>
#include <string>

struct Competiteur {
    long identifiant;
    std::string prenom;
    std::string filiere;
    int problemes_resolus;
    int penalite;
};

std::ostream& operator<<(std::ostream& flux, const Competiteur& c) {
    flux << std::left
         << std::setw(12) << c.identifiant
         << std::setw(18) << c.prenom
         << std::setw(20) << c.filiere
         << std::setw(8)  << c.problemes_resolus
         << std::setw(10) << c.penalite;
    return flux;
}

std::istream& operator>>(std::istream& flux, Competiteur& c) {
    return flux >> c.identifiant >> c.prenom >> c.filiere 
                >> c.problemes_resolus >> c.penalite;
}

La fonction enregistrer() démontre le polymoprhisme des flux grâce à la classe de base std::ostream :

void enregistrer(std::ostream& sortie, const std::vector<Competiteur>& liste) {
    for (const auto& elem : liste) {
        sortie << elem << '\n';
    }
}

Cette conception permet d'utiliser indifféremment std::cout ou std::ofstream sans modification de code, exploitant l'héritage dans la hiérarchie des flux C++.

Amélioration de la résilience aux erreurs

La fonction de chargement suivante intègre une validation ligne par ligne pour gérer les données corrompues :

std::vector<Competiteur> charger(const std::string& chemin) {
    std::ifstream entree(chemin);
    if (!entree) throw std::runtime_error("Échec ouverture: " + chemin);

    std::vector<Competiteur> resultat;
    std::string ligne;
    int numero_ligne = 0;

    while (std::getline(entree, ligne)) {
        numero_ligne++;
        if (ligne.empty()) continue;

        std::istringstream flux_ligne(ligne);
        Competiteur participant;
        
        if (flux_ligne >> participant) {
            resultat.push_back(participant);
        } else {
            std::cerr << "[ERREUR L." << numero_ligne << "] Format invalide\n";
        }
    }
    return resultat;
}

Cette approche évite les blocages dus aux données mal formatées, contrairement à l'implémentation originale qui ignorait les numéros de séquence et provoquait des erreurs silencieuses.

Système de gestion étudiante orienté objet

Classe Etudiant encapsulant les données avec méthodes d'accès sécurisées :

class Etudiant {
public:
    std::string obtenir_filiere() const;
    int obtenir_moyenne() const;
    
    friend std::ostream& operator<<(std::ostream&, const Etudiant&);
    friend std::istream& operator>>(std::istream&, Etudiant&);

private:
    int matricule;
    std::string nom;
    std::string filiere;
    int moyenne;
};

Le gestionnaire Gestionnaire implémente un tri multi-critères via expressions lambda :

void Gestionnaire::trier() {
    std::sort(etudiants.begin(), etudiants.end(), 
        [](const Etudiant& a, const Etudiant& b) {
            if (a.obtenir_filiere() != b.obtenir_filiere()) 
                return a.obtenir_filiere() < b.obtenir_filiere();
            return a.obtenir_moyenne() > b.obtenir_moyenne();
        }
    );
}

Cette structure permet une personnalisation flexible des critères de tri tout en respectant l'encapsulation des données.

Interface utilisateru interactive

Le menu principal gère les erreurs d'entrée avec nettoyage du flux :

void afficher_menu() {
    std::cout << "\n--- Gestion Étudiants ---\n"
              << "1: Charger données\n"
              << "2: Trier\n"
              << "3: Afficher\n"
              << "4: Sauvegarder\n"
              << "5: Quitter\n";
}

void demarrer_application() {
    Gestionnaire gestion;
    int choix;
    
    while (true) {
        afficher_menu();
        if (std::cin >> choix) {
            // Traitement des choix
        } else {
            std::cin.clear();
            std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
            std::cout << "Erreur: Entrez un nombre\n";
        }
    }
}

La gestion des exceptions dans les opérations critiques garantit une sortie propre lors d'échecs d'E/S.

Étiquettes: surcharge_operateurs_C++ gestion_exceptions flux_standard tri_lambda robustesse_donnees

Publié le 10 octobre à 14h07