/**
 * @file jeuneEtVieux.cpp
 * @author l'équipe pédagogique 
 * @version 1 03/12/05
 * @brief corrige du TD2 - Exercice 3
 * Structures de données et algorithmes - DUT1 Paris 5
 */
 
#include <cassert>
#include <iostream>
using namespace std;

/**
 * @brief Type date
 * invariant : la date doit être valide
*/
struct Date {
	unsigned short jour, mois, annee;
};

/**
 * @brief Saisie d'une date valide
 * @return la date saisie
 */
Date saisir() {
	Date d;
	cout << "jour, mois, année : "; 
	cin >> d.jour >> d.mois >> d.annee;
	return d;
}

/**
 * @brief Affiche une date
 * @param[in] d : la date à afficher
 */
void afficher(const Date& d) {
	cout << d.jour << '/' << d.mois << '/' <<d.annee;
}

/**
 * @brief Compare deux dates sur l'axe des temps
 * @param[in] d1 : 1er argument
 * @param[in] d2 : 2ème argument
 * @return un entier négatif si d1<d2, positif si d1>d2 et nul si d1==d2
 */
int comparer (const Date& d1, const Date& d2) {
	if (d1.annee != d2.annee)
		return (d1.annee - d2.annee);
	if (d1.mois != d2.mois)
		return (d1.mois - d2.mois);
	if (d1.jour != d2.jour)
		return (d1.jour - d2.jour);
	else return 0;
}

typedef Date Item;

/**
 * @brief Type des tableaux statiques d'items de capacité 30
 * Les fonctions "compare" et "afficher" doivent être définies
 * invariant : nbItems <= CAPACITE
*/
struct ConteneurTS {
	enum {CAPACITE = 30};	// Capacité du tableau
	Item tab[CAPACITE];		// Tableau des items
	unsigned int nbItems; 	// Nombre d'items stockés
};

/**
 * @brief Initialise un tableau d'items vide
 * de manière à ce qu'aucun élément ne soit stocké
 * @param[out] t : le tableau d'items
 */
void initialiserT(ConteneurTS& t) {
	t.nbItems=0;
}

/**
 * @brief Lecture d'un item d'un tableau d'items
 * @param[in] t : le tableau d'items
 * @param[in] i : l'indice de l'item dans le tableau
 * @return l'item au poste i
 * @pre i < t.nbItems   
 */
Item lireT(const ConteneurTS& t, unsigned int i) {
	assert (i < t.nbItems);
	return t.tab[i];
}

/**
 * @brief Ecrire un item dans un tableau d'items
 * @param[in,out] t : le tableau d'items
 * @param[in] i : l'indice où ecrire l'item
 * @param[in] item : l'item à ecrire
 * @pre i <= t.nbItems et t.nbItems < t.capacite  
 */
void ecrireT(ConteneurTS& t, unsigned int i, const Item& item) {
	assert ((i < t.nbItems) || ((i == t.nbItems) && (t.nbItems < ConteneurTS::CAPACITE)));
	t.tab[i] = item;
	if(i == t.nbItems)
		t.nbItems++;
}

/**
 * @brief Affichage des elements d'un tableau d'items
 * @param[in] t : le tableau d'items
 */
void afficherT(const ConteneurTS& t) {
	unsigned int i;
	for (i=0; i < t.nbItems; ++i) { // invariant : les éléments de 0 à i-1 
		                            // ont été affichés
		afficher(t.tab[i]); cout << "  ";
    }
	cout << endl;
}

/**
 * @brief Calcul des indices des valeurs extrema d'un tableau d'items
 * @param[in] t : le tableau d'items
 * @param[out] min : l'indice d'un plus petit element
 * @param[out] max : l'indice d'un plus grand element
 * @pre t ne doit pas etre vide
 */
void extremaT(const ConteneurTS& t, unsigned int& min, unsigned int& max) {
	assert(t.nbItems > 0);
	unsigned int i;
	for (i=1, min=0, max=0; i < t.nbItems; ++i)
		if (comparer (t.tab[i], t.tab[min]) <0)
			min=i;
    	else if(comparer(t.tab[i], t.tab[max])>0)
     			 max=i;
}

int main() {
	ConteneurTS datesNaissanceTD;
	initialiserT(datesNaissanceTD);
	Date d;
	int nbEtudiants;
	do {
		cout << "Nombre d'étudiants du TD (au max " 
	     	 << ConteneurTS::CAPACITE << ") : ";
		cin >> nbEtudiants;
	} while ((nbEtudiants <= 0) ||(nbEtudiants > ConteneurTS::CAPACITE));

	for (int i=0; i < nbEtudiants ; ++i) {  // invariant : i dates saisies
		d = saisir();            
		ecrireT(datesNaissanceTD, i, d);
	}
	
	cout << "\nLes dates de naissance des étudiants du TD : \n" << endl;
	afficherT(datesNaissanceTD);

   	unsigned int min, max;
	extremaT(datesNaissanceTD, min, max);
	cout << "\nLe(s) plus jeune(s) du TD est(sont) né(s) le : ";
	afficher(lireT(datesNaissanceTD, max)); 
	cout << "\nLe(s) plus vieux du TD est(sont) né(s) le : ";
	afficher(lireT(datesNaissanceTD, min));

	return 0;
}

