M2103-TP9-EXO-1-Corrigé

Fichier Date.h

/**
 *
 * \file     Date.h
 *
 * \authors  M. Laporte
 *
 * \date     24/05/2018
 *
 * \version  V1.0
 *
 * \brief    Declaration de la classe Date
 *
 **/
#ifndef __DATE_H__
#define __DATE_H__

#include <ctime> // struct tm

namespace std
{
    class Date : public tm
    {
      public :
        Date (void);

        unsigned getYear   (void) const;
        unsigned getMonth  (void) const;
        unsigned getDay    (void) const;
        unsigned getHour   (void) const;
        unsigned getMinute (void) const;
        unsigned getSecond (void) const;

    }; // Date
} // std

#endif /* __DATE_H__ */

Fichier Date.cpp

/**
 *
 * \file     Date.cpp
 *
 * \authors  M. Laporte
 *
 * \date     24/05/2018
 *
 * \version  V1.0
 *
 * \brief    Definitions de la classe Date
 *
 **/

#include "date.h"
std::Date::Date (void)
{
    time_t whatTime;
    time (& whatTime);
    tm local;
    local = * localtime (&whatTime);
    tm_year = local.tm_year; 
    tm_mon  = local.tm_mon;
    tm_mday = local.tm_mday;
    tm_hour = local.tm_hour;
    tm_min  = local.tm_min;
    tm_sec  = local.tm_sec;

    //*this = * ((Date *) localtime (&whatTime));

    tm_year += 1900;
    tm_mon += 1;

}

unsigned std::Date::getYear   (void) const { return tm_year; }
unsigned std::Date::getMonth  (void) const { return tm_mon;  }
unsigned std::Date::getDay    (void) const { return tm_mday; }
unsigned std::Date::getHour   (void) const { return tm_hour; }
unsigned std::Date::getMinute (void) const { return tm_min;  }
unsigned std::Date::getSecond (void) const { return tm_sec;  }


M2103-TP9-EXO-2

Le but de ce qui suit est de traduire en C++ le schéma UML suivant :

Dans l’espace de noms anonyme du fichier main.cpp déclarer la classe Message, comme elle est décrite sur le schéma UML. Y ajouter un constructeur qui se contente de remplir myContent avec un paramètre correspondant, et myDate, avec la date courante (constructeur par défaut de Date). La fonction displayContent() affiche à l’écran le contenu du message. Vous intégrerez directement les définitions des fonctions dans la classe.
Dans l’espace de noms anonyme, insérer les différentes classes (exercices suivants), de haut en bas, dans l’ordre des exercices. Normalement, seules des déclarations de classes vides seront à ajouter. Lorsque cela sera nécessaire un embryon de classe sera fourni.

Ajouter à la classe l’accesseur à l’attribut myDate.

Dans l’espace de noms anomyme ajouter les fonctions displayDate() suivante :

    void displayDate (const Date & date)
    {
        cout << date.getDay () << ' ' << date.getMonth () << ' ' << date.getYear ();
    
    } // displayDate()

et displayHour() suivante :

    void displayHour (const Date & date)
    {
        cout << date.getHour () << "h " << date.getMinute () 
             << "mn et " <

Tester avec la fonction testMessage() suivante, également à incorporer à l'espace de noms anonyme du fichier main.cpp :

    void testMessage (void)
    {
        Message message ("salut");
        message.displayContent ();
        cout << " posté le : ";
        displayDate (message.getDate ());
        cout << " à ";
        displayHour (message.getDate ());
        cout << endl;

    } // testMessage()}

M2103-TP9-EXO-3

Dans l’espace de noms anonyme du fichier main.cpp déclarer la classe PublicMessage, comme elle est décrite sur le schéma UML.
La fonction add() se contente d’incrémenter de 1 myLikers (nombre de personnes qui aiment ce message).
Ajouter l’accesseur à myNbLikers.
Tester avec la fonction testPublicMessage() suivante, à incorporer également à l’espace de noms anonyme.

    void testPublicMessage (void)
    {
        PublicMessage message ("salut");
        message.displayContent ();
        cout << " posté le : ";
        displayDate (message.getDate ());
        cout << " à ";
        displayHour (message.getDate ());
        cout << endl;
        for (unsigned i(0); i < 5; ++i)
            message.add ();
        cout << "Nb de likers : " << message.getNbLikers (); << endl;

    } // testPublicMessage()

M2103-TP9-EXO-3-Corrigé

    class PublicMessage : public Message
    {
        unsigned myNbLikers;
      public :
        PublicMessage (const string & content)
           : Message (content), myNbLikers (0) {}

        unsigned getNbLikers (void) const { return myNbLikers; }

        void add (void) { ++ myNbLikers; }

    }; // PublicMessage

M2103-TP9-EXO-4

Dans l’espace de noms anonyme du fichier main.cpp déclarer la classe PrivateMessage, comme elle est décrite sur le schéma UML. Le constructeur a la tâche supplémentaire d’initialiser le lien avec l’User.
Ajouter l’accesseur à ce lien.

Tester avec la fonction testPrivateMessage() et la classe User provisoire suivantes, à incorporer également à l’espace de noms anonyme.

    class User
    {
       public :
       void sendMessage (const PrivateMessage & message)
       {
           message.displayContent ();
           cout << endl;
       } // sendMessage()
       void addFriend (User * oneFriend) { cout << "ajouté" << endl; }
       User * getFriend (unsigned i) const { cout << i << endl; return new User; }
       System * getSystem (void) const { cout << "système" << endl; return NULL; }
       void addMessage (const PrivateMessage & message) { message.displayContent (); cout << endl; }
       
    }; // User
    
    void testPrivateMessage (void)
    {
        User user;
        PrivateMessage message ("salut", & user);
        message.displayContent ();
        cout << " posté le : ";
        displayDate (message.getDate ());
        cout << " à ";
        displayHour (message.getDate ());
        cout << endl;
        message.getSender ()->getFriend (5);

    } // testPrivateMessage()

M2103-TP9-EXO-5

Dans l’espace de noms anonyme du fichier main.cpp déclarer la classe User, comme elle est décrite sur le schéma UML. Le constructeur initialise les attribut, si nécessaire, aux valeurs des paramètres correspondants. Il ne faut surtout pas que les adresses des messages que génère l’User puissent changer. Il est donc absolument nécessaire de réserver assez de place pour ranger tous les messages (reserve (1000) devrait suffire.
Un utilisateur ne doit pas pouvoir modifier les messages qu’il a reçus, ils sont la propriété de leur émetteur.
La fonction sendMessage() est proposée aux amis de l’User, elle ajoute donc un message à la liste des messages reçus.
La fonction addMessage() sert à ajouter un message dans la liste des messages envoyés, de façon à pouvoir l’envoyer à un ami, par la suite, mais pas forcément maintenant.
Ajouter l’accesseur à l’attribut myName
Ajouter la méthodesgetSentMessage(), pour accéder au ième message envoyé. Attention ! On doit renvoyer le ième message, pas une copie de celui-ci. Attention encore, il est hors de question de pouvoir modifier ce message. C’est une référence sur un objet constant qu’il faut donc retourner.
Ajouter la méthodesgetRecievedMessage(), pour accéder au ième message reçu. Attention à nouveau ! Il est hors de question de pouvoir modifier ce message.

Ajouter les méthodes GetNbSentMessages(), GetNbFriends() et GetNbRecievedMessages().

Tester avec la fonction testUser() suivante :

    void testUser (void)
    {
        System oneSystem;
        User alfred    ("Alfred", NULL);
        User alain     ("Alain", NULL);
        User sophie    ("Sophie", NULL);
        User emmanuel  ("Emmanuel", NULL);
        User christian ("Christian", NULL);
        User petru     ("Petru", NULL);
        User marc      ("Marc", NULL);
        PrivateMessage message ("salut", & alfred);
        message.displayContent ();
        cout << endl;

        alain.addFriend (&sophie);
        alain.addFriend (&emmanuel);
        alain.addFriend (&christian);
        alain.addFriend (&petru);
        alain.addFriend (&marc);

        cout << "Alain a " << alain.getNbFriends () << " amis" << endl;
        cout << "Le troisième ami d'Alain est : " << (alain.getFriend (2))->getName () << endl;

        alfred.addMessage (message);
        alain.sendMessage (&message);
        cout << "Nombre de message envoyés par Alfred : " << alfred.getNbSentMessages ()   << endl;
        cout << "Nombre de message reçus par Alfred : " << alfred.getNbRecievedMessages () << endl;
        cout << "Nombre de message envoyés par Alain : " << alain.getNbSentMessages ()   << endl;
        cout << "Nombre de message reçus par Alain : " << alain.getNbRecievedMessages () << endl;
        alain.getRecievedMessage (0)->displayContent ();
        cout << endl;
        alfred.getSentMessage (0).displayContent ();
        cout << endl;

    } // testUser()

M2103-TP9-EXO-5-Corrigé

    class System;

    class User
    {
        string   myName;
        System * mySystem;
        vector <PrivateMessage>    mySentMessages;
        vector <PrivateMessager *> myRecievedMessages;
        vector <User *>            myFriends;

      public :
        User (const string & name, System * system = NULL) : myName (name), mySystem (system)
        {
            mySentMessages.reserve (20);
        }
        void addFriend (User * aFriend)
        {
           myFriends.push_back (aFriend);

        } // addFriend()

        const string & getName (void) const { return myName; }

        User * getFriend (unsigned i) const { return myFriends [i]; }

        const PrivateMessage & getSentMessage (unsigned i) const { return mySentMessages [i]; }

        const PrivateMessage * getRecievedMessage (unsigned i) const { return myRecievedMessages [i]; }

        System * getSystem (void) const { return mySystem; }

        unsigned getNbFriends        (void) const { return myFriends.size (); }

        unsigned getNbSentMessages   (void) const { return mySentMessages.size (); }

        unsigned getNbRecievedMessages (void) const { return myRecievedMessages.size ();  }

        void sendMessage (const PrivateMessage * message)
        {
            myRecievedMessages.push_back (message);

        } // sendMessage()

        void addMessage (const PrivateMessage & message)
        {
            mySentMessages.push_back (message);
        }

    }; // User

M2103-TP9-EXO-6

Dans l’espace de noms anonyme du fichier main.cpp déclarer la classe System, comme elle est décrite sur le schéma UML. Le constructeur sera utilisé, comme dans le TD3 (TP4) pour tester le programme.
La fonction getUser() renvoie le ième User (pas une copie).
Idem pour getPublicMessage().
Voici le constructeur :

        System (void) : myNbUsers (0), myNbMessages (0)
        {
            myUsers.reserve (1000);
            myPublicMessages.reserve (1000);
            // création des Users
            addUser ("Alfred");
            addUser ("Alain");
            addUser ("Sophie");
            addUser ("Emmanuel");
            addUser ("Christian");
            addUser ("Petru");
            addUser ("Marc");
            /* verification des Users */
            cout << myUsers.size () << endl;
            for (const User & user : myUsers)
            {
                cout << user.getName () << endl;
            }


            /* création de leurs amis * /
            for (unsigned i (0); i < myUsers.size (); ++i)
                for (unsigned j (0); j < myUsers.size () / 2; ++j)
                    myUsers [i].addFriend (&myUsers [(i + ((j * 2) + 1)) % myUsers.size ()]);

            /*  verification des amis  * /
            for (unsigned i (0); i < myUsers.size (); ++i)
            {
                User user = myUsers [i];
                cout << user.getName () << " a " << user.getNbFriends() << " amis : " << endl;
                for (unsigned j (0); j < user.getNbFriends (); ++j)
                    cout << (user.getFriend (j))->getName () << endl;
            }
            /*  création et envoi des messages privés  * /
            for (User & user : myUsers)
            {
                for (unsigned j (0); j < user.getNbFriends (); ++j)
                {
                    string content (string ("salut") + ' ' + (user.getFriend (j))->getName ());
                    PrivateMessage message (content, & user);
                    user.addMessage (message);
                    (user.getFriend (j))->sendMessage (&(user.getSentMessage (user.getNbSentMessages () - 1)));
                }
            }
            /*  vérifications des messages envoyés  * /
            for (unsigned i (0); i < myUsers.size (); ++i)
            {
                User user = myUsers [i];
                cout << user.getName () << " a envoyé " << user.getNbSentMessages() << " messages : " << endl;
                for (unsigned j (0); j < user.getNbSentMessages (); ++j)
                {
                    (user.getSentMessage (j)).displayContent();
                    cout << endl;
                }

            }
            /*  vérifications des messages reçus  * /
            for (unsigned i (0); i < myUsers.size (); ++i)
            {
                User user = myUsers [i];
                cout << user.getName () << " a reçu " << user.getNbRecievedMessages() << " messages : " << endl;
                for (unsigned j (0); j < user.getNbRecievedMessages (); ++j)
                {
                    cout << "de " << (user.getRecievedMessage (j))->getSender ()->getName () << " : ";
                    (user.getRecievedMessage (j))->displayContent();
                    cout << endl;
                }

            }
            /* création et envoie des messages publiques  * /
            string oneMessage ("a");
            for (const User & user : myUsers)
                for (unsigned i (0); i < 5; ++i)
                {
                    oneMessage += 'a';
                    (user.getSystem ())->addPublicMessage (oneMessage);
                }
            /* test de la création des messages * /
            for (const PublicMessage & message : myPublicMessages)
            {
                message.displayContent ();
                cout << endl;
            }
            /*  création des like  * /
            for (User & user : myUsers)
                for (unsigned i (0); i < myNbMessages; ++i)
                    (user.getSystem ())->getPublicMessage (i).add ();

            /*  test des likes * /
            for (const PublicMessage & message : myPublicMessages)
            {
                message.displayContent ();
                cout << " a " << message.getNbLikers () << " likers" << endl;
            }
/*    */

         } // System()

Dans la fonction main() il suffit de déclarer un objet System pour effectuer les tests.
Au fur et à mesure de vos mises au point, déplacer l'espace entre * et / d'un commentaire à l'autre.