Exercice : Pointeurs, structures et références

Exercice : Pointeurs, structures et références#

Attention: Dans cet exercice, les pointeurs et les références sont utilisés en fonction de ce qui est le plus approprié. Il est important d’être attentif au type des paramètres afin de ne pas faire d’erreurs. N’oubliez pas de bien tester chacune de vos fonctions au fur et à mesure.

Le but de cet exercice est de réaliser un système basique permettant à un fabriquant de voitures de gérer son stock ainsi que les garages exposant ses véhicules.

Le type Garage enregistre le nom et la capacité d’exposition d’un garage ainsi que le nombre de véhicules actuellement exposés et le chiffre d’affaire effectué. Le type Voiture quant à lui enregistre le code de la voiture, son prix et éventuellement un pointeur vers le garage où elle est exposée. Si la voiture n’est pas actuellement exposé ce pointeur doit avoir la valeur NULL.

Ces structures sont définies ci-dessous :

struct Garage {
    string nom;
    int nbvoitures;
    int capacite;
    int CA;
};
struct Voiture {
    string code;
    float prix;
    Garage *position;
};

Sur le même modèle que dans l’exercice 6 du TD4 (Fournitures), on utilisera des vecteurs de structures pour enregistrer la liste des garages et des voitures :

vector<Voiture> stock;
vector<Garage>  lieux;
  1. Écrire la fonction ajouteVoiture qui prend en paramètre une référence vers le stock, le code et le prix d’une voiture et qui ajoute dans le stock une nouvelle voiture actuellement non exposée.

    void ajouteVoiture(vector<Voiture> &stock, string code, float prix);

    Solution
    void ajouteVoiture(vector<Voiture> &stock, string code,
                       float prix) {
        Voiture v;
        v.code     = code;
        v.prix     = prix;
        v.position = NULL;
        stock.push_back(v);
    }
    
  2. De manière similaire, écrivez maintenant une fonction ajouteGarage qui prend en paramètre une référence vers la liste des lieux d’exposition, un nom et une capacité, et qui ajoute un nouveau garage. Le nombre de voitures exposées et le chiffre d’affaire seront initialisés à zéro.

    void ajouteGarage(vector<Garage> &lieux, string nom, int capacite);

    Solution
    void ajouteGarage(vector<Garage> &lieux, string nom,
                      int capacite) {
        Garage g;
        g.nom        = nom;
        g.capacite   = capacite;
        g.nbvoitures = 0;
        g.CA         = 0;
        lieux.push_back(g);
    }
    
  3. Écrivez maintenant deux fonctions permettant d’afficher la liste des voitures du stock ainsi que la liste des lieux d’exposition. Lors de l’affichage d’une voiture, si celle-ci est exposée dans un garage vous afficherez le nom de celui-ci.

    void afficheStock(vector<Voiture> stock);

    void afficheLieux(vector<Garage> lieux);

    Solution
    void afficheStock(vector<Voiture> stock) {
        for (int i = 0; i < stock.size(); i++) {
            Voiture v = stock[i];
            cout << "la voiture " << v.code << " vendue "
                 << v.prix << " kopek";
            if (v.position == NULL) {
                cout << " n'est actuellement pas exposée." << endl;
            } else {
                cout << " est visible au garage " << v.position->nom
                     << "." << endl;
            }
        }
    }
    void afficheLieux(vector<Garage> lieux) {
        for (int i = 0; i < lieux.size(); i++) {
            Garage g = lieux[i];
            cout << "le garage " << g.nom << " expose actuellement "
                 << g.nbvoitures << " voiture(s) et a un CA de "
                 << g.CA << endl;
        }
    }
    

    Remarque: Ici on n’a pas besoin de passage par référence, mais si on veut éviter la copie d’une grosse donnée (tableau de structures) on pourrait passer les paramètres par références constantes.

Nous allons maintenant définir deux fonctions outils permettant de faire des recherches dans le stock et les lieux d’expositions. Ces fonctions permettent de trouver un élément particulier et le renvoient s’il existe. Afin que les fonctions appelantes puissent modifier les éléments trouvés, il est nécéssaire de renvoyer non pas des copies de ces éléments mais des pointeurs vers les originaux.

  1. Écrivez la fonction chercheVoiture qui va parcourir le stock à la recherche d’une voiture dont le code est donné et renvoyer un pointeur vers la structure représentant cette voiture. Si aucune voiture ne correspond dans le stock, la fonction renvera un pointeur NULL.

    Voiture *chercheVoiture(vector<Voiture> &stock, string code);

    Solution

    Ici on a besoin de passage par référence, car on veut renvoyer un pointeur sur la voiture cherchée. Si on ne fait pas un passage par référence, on aurait un pointeur sur une copie temporaire du tableau des voitures, qui ne serait plus alloué en sortie de la fonction.

    Voiture *chercheVoiture(vector<Voiture> &stock, string code) {
        for (int i = 0; i < stock.size(); i++)
            if (stock[i].code == code)
                return &stock[i];
        return NULL;
    }
    

    Autre solution:

    Voiture *chercheVoiture(vector<Voiture> &stock, string code) {
        Voiture *p = NULL;
        for (int i = 0; i < stock.size(); i++) {
            if(code == stock[i].code){
                *p = stock[i];
            }
        }
        return p; // non pas *p, mais p (on doit renvoyer un
                  // pointeur, pas une valeur sur laquelle pointe
                  // un pointeur)
    }
    
  2. Écrivez la fonction chercheGarage qui va parcourir la liste des lieux d’exposition afin de trouvez un garage disposant de place pour exposer une voiture et renvoyer un pointeur vers la structure le représentant. Si tous les garages sont actuellement pleins, la fonction renverra un pointeur NULL.

    Garage *chercheGarage(vector<Garage> &lieux);

    BEGIN SOLUTION

    Garage *chercheGarage(vector<Garage> &lieux) {
        for (int i = 0; i < lieux.size(); i++)
            if (lieux[i].nbvoitures < lieux[i].capacite)
                return &lieux[i];
        return NULL;
    }
    ```cpp
    
    END SOLUTION
    

Nous allons maintenant utiliser ces fonctions afin d’implémenter les outils nécessaires à la gestion du parc de voitures.

  1. Écrivez la fonction exposeVoiture qui va chercher une voiture de code donné dans le stock et la met en exposition dans un garage si :

    • une voiture avec ce code existe ;

    • elle n’est pas déjà exposée ;

    • un garage dispose de place pour l’exposer.

    Si toutes les conditions sont remplies, toutes les structures concernées doivent êtres mises-à-jour et la valeur true renvoyée. Sinon, aucune modification ne doit être réalisée et la valeur false doit être renvoyée.

    bool exposeVoiture(vector<Voiture> &stock, vector<Garage> &lieux, string code);

    BEGIN SOLUTION

    bool exposeVoiture(vector<Voiture> &stock, vector<Garage> &lieux,
                       string code) {
        Voiture *v = chercheVoiture(stock, code);
        // Test si non existante ou déjà exposée
        if (v == NULL || v->position != NULL)
            return false;
        Garage *g = chercheGarage(lieux);
        if (g == NULL)
            return false;
        v->position = g;
        g->nbvoitures++;
        return true;
    }
    ```cpp
    
    END SOLUTION
    
  2. Écrivez la fonction vendVoiture qui va marquer une voiture de code donné comme n’étant plus exposée et mettre-à-jour les informations du garage qui l’exposait (et renvoyer true si une voiture de ce code existe et est exposée, sinon aucune modification et renvoie false).

    bool vendVoiture(vector<Voiture> &stock, string code);

    BEGIN SOLUTION

    bool vendVoiture(vector<Voiture> &stock, string code) {
        Voiture *v = chercheVoiture(stock, code);
        if (v == NULL || v->position == NULL)
            return false;
        v->position->nbvoitures - -;
        v->position->CA += v->prix;
        v->position = NULL;
        return true;
    }
    ```cpp
    
    END SOLUTION