Partage

[Exercices] Venez vous entraîner !

(v2)

17 juillet 2011 à 19:10:11

@Equinoxe : c'est pas précisé. Tu fais comme tu veux. Mais quelqu'un soucieux de l'optimisation ne chargerait pas tout... surtout si tu imagines une bibliothèque avec autant de livres que wikipedia a d'articles...
Après, une petite astuce consisterait à découper en plusieurs fichiers selon le genre (de 0 à 9 pour commencer)...
17 juillet 2011 à 21:02:00

Sauf que même 1M d'articles avec des tailles de (10 (numero) + 20 (Titre) + 20 (Genre) + 20 (Auteur) = 70) octets fait à peine 70 Mo.
Sur ce point, je pense que même tout wikipédia (qui ne doit pas contenir plus de 10 millions d'articles, soit 700Mo) devrait tenir en mémoire, même en considérant un léger poids supplémentaire de moins d'un Mo pour les variables temporaires, de ~10Mo pour toutes les informations nécessaires pour enregistrer les 10M articles, et encore 700 Mo en cas de nécessité de variable temporaire copiant tout la BDD (mauvaise prog' + requête particulière, pour mon cas tous les résultats d'une recherche sont copiés), soit un total d'environ 1410Mo, ce qui tient largement.

Par contre, un B-Tree-like devient nettement plus complexe si on veut gérer l'accès à la mémoire "disque", et devient nettement plus lent dès qu'on va rechercher par titre, par exemple.

Enfin, j'ai terminé le niveau 2 pour le moment, je m'attaquerai au 3 demain. :)
17 juillet 2011 à 22:09:59

pourquoi veux tu mettre tout en mémoire ?
Anonyme
17 juillet 2011 à 22:34:21

Citation : LoiCpp

pourquoi veux tu mettre tout en mémoire ?

Pour les performance (la RAM est plus rapide que le disque) je suppose.
17 juillet 2011 à 23:37:47

Et aussi par flemme, utiliser boost.serialize est tellement pratique. :-°
18 juillet 2011 à 0:20:42

ouai mais bon 70MO dans la mémoire c'est du gaspillage... pour un texte sur console, la lecture sur le disque est tellement plus simple (je sais pas si c'est possible d'avoir des événements par contre sur console :p )
18 juillet 2011 à 10:22:00

Citation : LoiCpp

ouai mais bon 70MO dans la mémoire c'est du gaspillage... pour un texte sur console, la lecture sur le disque est tellement plus simple (je sais pas si c'est possible d'avoir des événements par contre sur console :p )


Hum, tu peux récupérer les évents du clavier uniquement à la base (avec la bibli standard j'entends)...
18 juillet 2011 à 12:07:19

Quand on parle d'une appli biblio, faite pour tourner sur un serveur et être accédée par des clients (à la base), le serveur devrait avoir au moins 1Go de RAM, avec ... 128 Mo (J'avance un chiffre au pif, il me semble qu'une distrib' linux console prend encore moins) de RAM pour l'OS, il reste 896Mo de RAM réservée au programme. Et il est de plus en plus dur de n'avoir qu'un Go de RAM, donc je pense que 70Mo ne sont pas trop (et c'est déjà à condition d'avoir 1M de livres dans la bibliothèque, ce qui, il me semble, est relativement rare. :p ).
18 juillet 2011 à 12:10:39

Hum, après, l'utilisateur il s'en fout carrément de la Ram. Lui ce qui l'intéresse, c'est la vitesse. Donc ouais, peut-être...
18 juillet 2011 à 17:10:17

@Equinoxe: L'affichage des messages par les différentes classes est là pour faire pratiquer. Le but est de placer les messages au bon endroit (constructeur, destructeur, etc.) afin d'obtenir l'affichage voulu. Cela fait réviser l'ordre d'appel des constructeurs/destructeurs etc.
Co-auteur du cours de C++. ||| Posez vos questions sur le forum ||| Me contacter.
18 juillet 2011 à 17:22:54

Salut, :)

Voici mon code pour l'exercice de germino Biblio++.

Il me reste 1-2 méthodes à implémenter, et 2-3 bugs à corriger mais rien de bien grave, donc j'éditerai au fur et à mesure. ;)

Je n'ai pas fait réellement un niveau précis, car le niveau 4 est en place mais je n'ai pas géré les dates qui sont au niveau 3.

main.cpp
#include "Library.h"

int main(void)
{
    Library* library = new Library();
    return library->menu();
}

bool operator==(Author a1, Author a2)
{
    return (a1.firstName == a2.firstName) && (a1.surname == a2.surname);
}

main.h
#ifndef MAIN_H_INCLUDED
#define MAIN_H_INCLUDED

#include <string>

typedef int id;

typedef struct
{
    std::string firstName;
    std::string surname;
}Author;

bool operator==(Author a1, Author a2);

#endif


Book.h
#ifndef BOOK_H_INCLUDED
#define BOOK_H_INCLUDED

#include <string>

#include "main.h"

class Book
{
    public :

        Book();
        ~Book();
        Book(id, Author, std::string, std::string);

        void edit(id, Author, std::string, std::string);
            void editId(id);
            void editAuthor(Author);
            void editTitle(std::string);
            void editType(std::string);

        int loan(id);
        int restore();

        void show(void);

        Author author(void);
        std::string authorFirstName(void);
        std::string authorSurname(void);
        std::string title(void);
        std::string type(void);
        id getId(void);

        id idLoaner(void);

    private :

        id m_id;
        Author m_author;
        std::string m_title;
        std::string m_type;
        id m_loaner;
        bool m_here;
};

#endif

Book.cpp
#include <iostream>

#include "Book.h"

Book::Book()
{
    m_here = true;
}
Book::~Book()
{
}

Book::Book(id i, Author author, std::string title, std::string type)
{
    Book::edit(i,author,title,type);
    m_here = true;
}

void Book::edit(id i, Author author, std::string title, std::string type)
{
    m_id = i;
    m_author = author;
    m_title = title;
    m_type = type;
}
void Book::editId(id i)
{
    m_id = i;
}
void Book::editAuthor(Author author)
{
    m_author = author;
}
void Book::editTitle(std::string title)
{
    m_title = title;
}
void Book::editType(std::string type)
{
    m_type = type;
}

int Book::loan(id loaner)
{
    if (m_here == false || loaner == -1)
        return -1;
    m_here = false;
    m_loaner = loaner;
    return 0;
}

int Book::restore()
{
    if (m_here)
        return -1;
    m_here = true;
    return 0;
}

void Book::show(void)
{
    std::cout << "___________________________________________" << std::endl
         << "|   " << m_title << std::endl
         << "|                                          " << std::endl
         << "|             By " << m_author.firstName << " " << m_author.surname << std::endl
         << "|                                          " << std::endl
         << "| idBook -> " << m_id << std::endl
         << "|                                          " << std::endl;
    if (m_here)
        std::cout << "|  Available " << std::endl;
    else
        std::cout << "|  Not Available (member " << m_loaner << " have)" << std::endl;
    std::cout << "___________________________________________" << std::endl;
}

Author Book::author(void)
{
    return m_author;
}
std::string Book::authorFirstName(void)
{
    return m_author.firstName;
}
std::string Book::authorSurname(void)
{
    return m_author.surname;
}
std::string Book::title(void)
{
    return m_title;
}
std::string Book::type(void)
{
    return m_type;
}
id Book::idLoaner(void)
{
    return m_loaner;
}
id Book::getId(void)
{
    return m_id;
}


Member.h
#ifndef MEMBER_H_INCLUDED
#define MEMBER_H_INCLUDED

#include <string>
#include <vector>

#include "main.h"

class Book;

class Member
{
    public :

        Member();
        ~Member();
        Member(id,std::string,std::string);
        void edit(id,std::string,std::string);

        void addLoan(Book*);
        int removeLoan(Book*);

        void show(void);

        std::string firstName(void);
        std::string surname(void);
        id getId(void);
        size_t nbLoan(void);
        Book* book(id);

    private :

        std::string m_firstName;
        std::string m_surname;
        id m_id;
        std::vector<Book*> m_loan;
};

#endif

Member.cpp
#include <iostream>

#include "Member.h"
#include "Book.h"

Member::Member(){}
Member::~Member()
{
    m_loan.clear();
}

Member::Member(id i, std::string firstName, std::string surname)
{
    Member::edit(i,firstName,surname);
}

void Member::edit(id i, std::string firstName, std::string surname)
{
    m_id = i;
    m_firstName = firstName;
    m_surname = surname;
}

/* Méthodes d'ajout / suppression de membre */
    void Member::addLoan(Book* book)
    {
        m_loan.push_back(book);
    }
    int Member::removeLoan(Book* book)
    {
        for (unsigned i = 0; i < m_loan.size(); ++i)
            if (book == m_loan[i])
            {
                m_loan.erase(m_loan.begin() + i);
                return 0;
            }
        return -1;
    }
void Member::show(void)
{
    std::cout << "_______________________________________" << std::endl
              << "| " << m_surname << " " << m_firstName   << std::endl
              << "| "                                      << std::endl
              << "| " << m_loan.size() << " books loaned"  << std::endl;

    for (unsigned i = 0; i < m_loan.size(); ++i)
        if (m_loan[i] != NULL)
            std::cout << "|      " << m_loan[i]->title() << " (by " << m_loan[i]->authorFirstName() << " " << m_loan[i]->authorSurname() << ")" << std::endl;
        else
            std::cout << "|      (unknow book)" << std::endl;
}

/* */
    std::string Member::firstName(void)
    {
        return m_firstName;
    }
    std::string Member::surname(void)
    {
        return m_surname;
    }
    size_t Member::nbLoan(void)
    {
        return m_loan.size();
    }
    Book* Member::book(id i)
    {
        if (i < static_cast<int>(m_loan.size()))
            return m_loan[i];
        return NULL;
    }
    id Member::getId(void)
    {
        return m_id;
    }


Shelf.h
#ifndef SHELF_H_INCLUDED
#define SHELF_H_INCLUDED

#include <vector>

#include "main.h"
#include "Book.h"

class Shelf
{
    public :

        Shelf();
        ~Shelf();

        id addBook(Book*);
        id addBook(Author,std::string,std::string);

        id currentId(void);

        int removeBook(Book*);
        int removeBook(id);

        void show(void);
            int showOne(id);
            int showByAuthor(Author);
            int showByType(std::string);

        Book* book(id);

    private :

        std::vector<Book*> m_books;
        unsigned int m_count;
};

#endif

Shelf.cpp
#include "Shelf.h"

Shelf::Shelf()
{
    m_count = 0;
    m_books.resize(0);
}
Shelf::~Shelf()
{
    for (unsigned i = 0; i < m_books.size(); ++i)
        delete m_books[i];
}

/* Méthodes d'ajout / suppression des livres */

    id Shelf::addBook(Book* book)
    {
        m_books.push_back(book);
        return m_count++;
    }

    id Shelf::addBook(Author author, std::string title, std::string type)
    {
        m_books.push_back(new Book(m_count, author, title, type));
        return m_count++;
    }

    int Shelf::removeBook(Book* book)
    {
        for (unsigned i = 0; i < m_books.size(); ++i)
            if (book == m_books[i])
            {
                m_books.erase(m_books.begin() + i);
                return 0;
            }
        return -1;
    }
    int Shelf::removeBook(id i)
    {
        if (i > static_cast<int>(m_books.size()))
            return -1;
        m_books.erase(m_books.begin() + i);
        return 0;
    }

/* Méthodes d'affichage des livres */

    /* Affiche tous les livres */
    void Shelf::show(void)
    {
        for (unsigned i = 0; i < m_books.size(); ++i)
            m_books[i]->show();
    }
    /* Affiche un livre */
    int Shelf::showOne(id i)
    {
        if (i > static_cast<int>(m_books.size()))
            return -1;
        m_books[i]->show();
        return 0;
    }
    /* Affiche tous les livres d'un auteur */
    int Shelf::showByAuthor(Author author)
    {
        int showed = 0;
        for (unsigned i = 0; i < m_books.size(); ++i)
            if (m_books[i]->author() == author)
            {
                m_books[i]->show();
                showed++;
            }
        return showed;
    }
    /* Affiche tous les livres d'un certain genre */
    int Shelf::showByType(std::string type)
    {
        int showed = 0;
        for (unsigned i = 0; i < m_books.size(); ++i)
            if (m_books[i]->type() == type)
            {
                m_books[i]->show();
                showed++;
            }
        return showed;
    }

/* Retourne un pointeur vers le livre portant l'id passé en paramètre */
Book* Shelf::book(id i)
{
    if (i > static_cast<int>(m_books.size()))
        return NULL;
    return m_books[i];
}

/* Retourne le nombre de livres -1 */
id Shelf::currentId(void)
{
    return m_count;
}


MemberList.h
#ifndef MEMBER_LIST_H_INCLUDED
#define MEMBER_LIST_H_INCLUDED

#include <vector>

#include "main.h"
#include "Member.h"

class MemberList
{
    public :

        MemberList();
        ~MemberList();

        id addMember(Member*);
        id addMember(std::string,std::string);

        Member* member(id);

        int size(void);

        void show(void);

    private :

        std::vector<Member*> m_members;
        unsigned int m_count;
};

#endif

MemberList.cpp
#include "MemberList.h"

MemberList::MemberList()
{
    m_count = 0;
}
MemberList::~MemberList()
{
    m_members.clear();
}

id MemberList::addMember(Member* member)
{
    m_members.push_back(member);
    return m_count++;
}
id MemberList::addMember(std::string firstName, std::string surname)
{
    m_members.push_back(new Member(m_count, firstName, surname));
    return m_count++;
}

Member* MemberList::member(id i)
{
    if (i > static_cast<int>(m_members.size()))
        return NULL;
    return m_members[i];
}

int MemberList::size(void)
{
    return m_members.size();
}

void MemberList::show(void)
{
    for (unsigned i = 0; i < m_members.size(); ++i)
        m_members[i]->show();
}


Library.h
#ifndef LIBRARY_H_INCLUDED
#define LIBRARY_H_INCLUDED

#include <fstream>

#include "Shelf.h"
#include "MemberList.h"
#include "Book.h"

class Library
{
    public :

        Library();
        ~Library();

        int menu(void);

    private :

        void load(void);
            void loadBooks(void);
            void loadMembers(void);
        void save(void);
            void saveBooks(void);
            void saveMembers(void);

        /* Menu des livres */
        void booksMenu(void);
            void addBook(void);
            void chooseBookToEdit(void);
                void editBook(int);
                void editBook(std::string);
                void editBook(Author);
            void removeBook(void);
            void showBooks(void);

        /* Menu des membres */
        void membersMenu(void);
            void addMember(void);
            void memberInfo(void);
                void memberId(unsigned int);
                    void loanBookMenu(unsigned int);
                        void loanBook(unsigned int, unsigned int);
                    void restoreBook(unsigned int);
                    void editMember(unsigned int);
            void showMembers(void);


        /* Méthodes qui demandent des informations à l'utilisateur */
            Author getAuthor(void);
            std::string getInfo(std::string);
            unsigned int getBookId(void);
            unsigned int getMemberId(void);
            bool confirm(std::string);


        Shelf* m_shelf;        // Etagère
        MemberList* m_members; // Liste des membres

        /* Flux de lecture/sauvegarde */
        std::ifstream* m_loadBooks;
        std::ifstream* m_loadMembers;
        std::ofstream* m_saveBooks;
        std::ofstream* m_saveMembers;

        bool saved;
};

#endif


J'ai ensuite décidé de diviser les méthodes de la classe Library (je ne sais pas si c'est une pratique courante...). En tout cas c'est bien mieux ainsi pour s'y repérer. ;)

Library.cpp
#include <iostream>

#include "Library.h"

Library::Library()
{
    m_shelf = new Shelf();
    m_members = new MemberList();
}

Library::~Library()
{
    delete m_shelf;
    delete m_members;
    delete m_loadBooks;
    delete m_loadMembers;
    delete m_saveBooks;
    delete m_saveMembers;
}

/* Menu général (boucle principale du programme) */
int Library::menu(void)
{
    Library::load();
    int choice;
    while (1)
    {
        std::cout << std::endl
                  << "Choose an action "  << std::endl
                  << std::endl
                  << "   1- Books menu"    << std::endl
                  << "   2- Members menu"  << std::endl
                  << "   3- Save"          << std::endl
                  << "   4- Quit"          << std::endl
                  << "--> ";

        std::cin >> choice;
        if (choice < 1 || choice > 4)
        {
            std::cout << std::endl << "Invalid choice" << std::endl;
            continue;
        }
        if (choice == 1)
            Library::booksMenu();
        else if (choice == 2)
            Library::membersMenu();
        else if (choice == 3)
            Library::save();
        else
            break;
    }
    return 0;
}


LibraryLoad.cpp
/*
    Méthodes de chargement des données de la classe Library
*/

#include <iostream>

#include "Library.h"

void Library::load(void)
{
    Library::loadBooks();
    Library::loadMembers();
}

    void Library::loadMembers(void)
    {
        m_loadMembers = new std::ifstream("member.txt", std::ios::in);
        if (m_loadMembers->fail())
        {
            std::cerr << "Base de données des membres introuvable" << std::endl;
            return;
        }
        int nbMembers;
        *m_loadMembers >> nbMembers;

        /* Chargement des données des membres */
        int i = 0;
        int nbLoan, idLoan;
        std::string firstName, surname;
        std::cout << "Loaded members " << i << " of " << nbMembers << std::endl;
        while (i != nbMembers)
        {
            /* Nom, prénom, nombre d'emprunts */
            *m_loadMembers >> firstName >> surname >> nbLoan;
            m_members->addMember(firstName, surname);

            /* Identifiants des livres empruntés et recherche du Book* correspondant */
            for (int j = 0; j < nbLoan; ++j)
            {
                *m_loadMembers >> idLoan;
                m_members->member(i)->addLoan(m_shelf->book(idLoan));
            }
            i++;
            std::cout << "               " << i << " of " << nbMembers << std::endl;
        }
        std::cout << std::endl;
        m_loadMembers->close();
    }

    void Library::loadBooks(void)
    {
        m_loadBooks = new std::ifstream("book.txt", std::ios::in);
        if (m_loadBooks->fail())
        {
            std::cerr << "Base de données des livres introuvable" << std::endl;
            return;
        }
        int nbBooks;
        *m_loadBooks >> nbBooks;

        /* Chargement des données des livres */
        int i = 0;
        std::string title = "", author1, author2, type;
        std::string wordTitle;
        int idLoaner = 0;
        std::cout << "Loaded books " << i << " of " << nbBooks << std::endl;
        while (i != nbBooks)
        {
            /* Données de base (auteur, titre, genre) */

            /* Lecture du titre */
                wordTitle = "";
                title = "";
                *m_loadBooks >> wordTitle;
                while (wordTitle != "endOfTitle")
                {
                    title += wordTitle + " ";
                    wordTitle = "";
                    *m_loadBooks >> wordTitle;
                }

            /* Lecture de l'auteur et du type */
            *m_loadBooks >> author1 >> author2 >> type;
            Author a;
            a.firstName = author1;
            a.surname = author2;
            m_shelf->addBook(a,title,type);

            /* id de l'emprunteur du livre (-1 s'il n'y en a pas) */
            *m_loadBooks >> idLoaner;
            m_shelf->book(i)->loan(idLoaner);

            i++;
            std::cout << "             " << i << " of " << nbBooks << std::endl;
        }
        m_loadBooks->close();
    }


LibrarySave.cpp
/*
    Méthodes de sauvegarde des données de la classe Library
*/

#include <iostream>

#include "Library.h"

void Library::save(void)
{
    Library::saveBooks();
    Library::saveMembers();
}

    void Library::saveBooks(void)
    {
        m_saveBooks = new std::ofstream("book.txt", std::ios::out | std::ios::trunc);
        if (m_saveBooks->fail())
        {
            std::cerr << "Base de données des livres introuvable... Sauvegarde annulée" << std::endl;
            return;
        }
        *m_saveBooks << m_shelf->currentId() << "\n";

        /* Boucle de sauvegarde de chaque livre */
        std::cout << "Saved books 0 of " << m_shelf->currentId() << std::endl;
        for (int i = 0; i < m_shelf->currentId(); ++i)
        {
            *m_saveBooks << m_shelf->book(i)->title()           << " endOfTitle "
                         << m_shelf->book(i)->authorFirstName() << " "
                         << m_shelf->book(i)->authorSurname()   << " "
                         << m_shelf->book(i)->type()            << " "
                         << m_shelf->book(i)->idLoaner() << " \n";
            std::cout << "            " << i << " of " << m_shelf->currentId() << std::endl;
        }

        std::cout << std::endl << "Books saved successfully." << std::endl;
        m_saveBooks->close();
    }

    void Library::saveMembers(void)
    {
        m_saveMembers = new std::ofstream("member.txt", std::ios::out | std::ios::trunc);
        if (m_saveMembers->fail())
        {
            std::cerr << "Base de données des membres introuvable... Sauvegarde annulée" << std::endl;
            return;
        }
        std::cout << "Saved members 0 of " << m_shelf->currentId() << std::endl;
        *m_saveMembers << m_members->size() << "\n";

        /* Boucle de sauvegarde de chaque membre */
        for (int i = 0; i < m_members->size(); ++i)
        {
            *m_saveMembers << m_members->member(i)->firstName() << " "
                           << m_members->member(i)->surname()   << " "
                           << m_members->member(i)->nbLoan()    << " ";
            for (unsigned int j = 0; j < m_members->member(i)->nbLoan(); ++j)
                *m_saveMembers << m_members->member(i)->book(j)->getId() << " ";
            std::cout << "              " << i+1 << " of " << m_shelf->currentId() << std::endl;
            *m_saveMembers << "\n";
        }
        std::cout << std::endl << "Members saved successfully." << std::endl;
        m_saveMembers->close();
    }


LibraryBookMenu
/*
    Méthodes du menu des livres de la classe Library
*/

#include <iostream>

#include "Library.h"

void Library::booksMenu(void)
{
    int choice;
    while(1)
    {
        std::cout << std::endl
                  << std::endl
                  << "   1- Add a book"        << std::endl
                  << "   2- Edit a book"       << std::endl
                  << "   3- Remove a book"     << std::endl
                  << "   4- Show"              << std::endl
                  << "   5- Return"            << std::endl
                  << "--> ";
        std::cin >> choice;
        if (choice < 1 || choice > 5)
        {
            std::cout << std::endl << "Invalid choice" << std::endl;
            continue;
        }
        if (choice == 1)
            Library::addBook();
        else if (choice == 2)
            Library::chooseBookToEdit();
        else if (choice == 3)
            Library::removeBook();
        else if (choice == 4)
            Library::showBooks();
        else
            return;
    }
}

void Library::addBook(void)
{
    std::string title = Library::getInfo("Title ? --> ");
    std::string type = Library::getInfo("Type ? --> ");
    m_shelf->addBook(Library::getAuthor(),title, type);
}

/* Menu d'édition des données des livres */
void Library::chooseBookToEdit(void)
{
    int choice;
    while(1)
    {
        std::cout << std::endl
                  << "Edit book..."
                  << std::endl
                  << "   1- With id..."    << std::endl
                  << "   2- With author"   << std::endl
                  << "   3- With type"     << std::endl
                  << "   4- Return"        << std::endl
                  << "--> ";
        std::cin >> choice;
        if (choice < 1 || choice > 4)
        {
            std::cout << std::endl << "Invalid choice" << std::endl;
            continue;
        }
        if (choice == 1)
            Library::editBook(Library::getBookId());
        else if (choice == 2)
            Library::editBook(Library::getAuthor());
        else if (choice == 3)
            Library::editBook(Library::getInfo("Type ? --> "));
        else
            return;
    }
}

    /* Permet de changer n'importe quelle information sur le livre portant l'id passé en paramètre */
    void Library::editBook(int i)
    {
        int choice;
        while(1)
        {
            std::cout << std::endl
                      << std::endl
                      << "   1- Edit all"    << std::endl
                      << "   2- Edit author" << std::endl
                      << "   3- Edit title"  << std::endl
                      << "   4- Edit type"   << std::endl
                      << "   5- Return"      << std::endl
                      << "--> ";
            std::cin >> choice;
            if (choice < 1 || choice > 5)
            {
                std::cout << std::endl << "Invalid choice" << std::endl;
                continue;
            }
            if (choice == 1)
            {
                m_shelf->book(i)->editTitle(Library::getInfo("Title ? --> "));
                m_shelf->book(i)->editAuthor(Library::getAuthor());
                m_shelf->book(i)->editType(Library::getInfo("Type ? --> "));
            }
            else if (choice == 2)
                m_shelf->book(i)->editAuthor(Library::getAuthor());
            else if (choice == 3)
                m_shelf->book(i)->editTitle(Library::getInfo("Title ? --> "));
            else if (choice == 4)
                m_shelf->book(i)->editType(Library::getInfo("Type ? --> "));
            else
                return;
        }
    }

    /* Remplace un genre par un autre */
    void Library::editBook(std::string type)
    {
        int count = 0;
        std::vector<int> idBook(0);
        for (int i = 0; i < m_shelf->currentId(); ++i)
            if (m_shelf->book(i)->type() == type)
            {
                count++;
                idBook.push_back(i);
            }
        std::cout << std::endl
                  << count << " Books selected." << std::endl
                  << "Choose a new type :"       << std::endl
                  << std::endl;
        for (unsigned i = 0; i < idBook.size(); ++i)
            m_shelf->book(idBook[i])->editType(Library::getInfo("Type ? --> "));
    }

    /* Remplace un nom d'auteur par un autre sur tous ses livres */
    void Library::editBook(Author author)
    {
        int count = 0;
        std::vector<int> idBook(0);
        for (int i = 0; i < m_shelf->currentId(); ++i)
            if (m_shelf->book(i)->author() == author)
            {
                count++;
                idBook.push_back(i);
            }
        std::cout << std::endl
                  << count << " Books selected." << std::endl
                  << "Choose a new author :"       << std::endl
                  << std::endl;
        Author a = Library::getAuthor();
        for (unsigned i = 0; i < idBook.size(); ++i)
            m_shelf->book(idBook[i])->editAuthor(a);
    }

void Library::removeBook(void)
{
    std::string choice;
    int id = Library::getBookId();
    m_shelf->book(id)->show();
    if (Library::confirm("Are yous sure to delete this book ?"));
        m_shelf->removeBook(id);
}

void Library::showBooks(void)
{
    m_shelf->show();
}


LibraryMemberMenu.cpp
/*
    Méthodes du menu des membres de la classe Library
*/

#include <iostream>

#include "Library.h"

void Library::membersMenu(void)
{
    int choice;
    while(1)
    {
        std::cout << std::endl
                  << std::endl
                  << "   1- Add a member"      << std::endl
                  << "   2- Member..."         << std::endl
                  << "   3- Show"              << std::endl
                  << "   4- Return"              << std::endl
                  << "--> ";
        std::cin >> choice;
        if (choice < 1 || choice > 7)
        {
            std::cout << std::endl << "Invalid choice" << std::endl;
            continue;
        }
        if (choice == 1)
            Library::addMember();
        else if (choice == 2)
            Library::memberInfo();
        else if (choice == 3)
            Library::showMembers();
        else
            return;
    }
}

    void Library::addMember(void)
    {
        std::string firstName = Library::getInfo("First Name ? --> ");
        std::string surname = Library::getInfo("Surame ? --> ");
        m_members->addMember(firstName, surname);
    }
    /* Méthode qui permet de se rendre au menu d'un membre */
    void Library::memberInfo(void)
    {
        int choice;
        while(1)
        {
            std::cout << std::endl
                      << std::endl
                      << "Search by..."    << std::endl
                      << "    1- Id"       << std::endl
                      << "    2- Surname"  << std::endl
                      << "    3- Return"   << std::endl
                      << "--> ";
            std::cin >> choice;
            if (choice < 1 || choice > 3)
            {
                std::cout << std::endl << "Invalid Choice" << std::endl;
                continue;
            }
            if (choice == 1)
                Library::memberId(Library::getMemberId());
            else if (choice == 2)
            {
                std::vector<unsigned int> idMembers(0);
                std::string surname = Library::getInfo("\nSurname ? --> ");
                for (int i = 0; i < m_members->size(); ++i)
                    if (m_members->member(i)->surname() == surname)
                        idMembers.push_back(i);

            }
            else
                return;
        }
    }
        /* Menu d'un membre */
        void Library::memberId(unsigned int i)
        {
            m_members->member(i)->show();
            int choice;
            while(1)
            {
                std::cout << std::endl
                          << std::endl
                          << "   1- Loan"     << std::endl
                          << "   2- Restore"  << std::endl
                          << "   3- Edit"     << std::endl
                          << "   4- Return"   << std::endl
                          << "--> " << std::endl;

                std::cin >> choice;
                if (choice < 1 || choice > 4)
                {
                    std::cout << std::endl << "Invalid Choice" << std::endl;
                    continue;
                }
                if (choice == 1)
                    Library::loanBookMenu(i);
                else if (choice == 2)
                    Library::restoreBook(i);
                else if (choice == 3)
                    Library::editMember(i);
                else
                    return;
            }
        }
            /* Menu d'emprunt */
            void Library::loanBookMenu(unsigned int idMember)
            {
                int choice;
                while(1)
                {
                    std::cout << std::endl
                              << std::endl
                              << "Choose a book..."        << std::endl
                              << "   1- With Id"           << std::endl
                              << "   2- Search by Title"   << std::endl
                              << "   3- Search by Author"  << std::endl
                              << "   4- Search by Type"    << std::endl
                              << "   5- Return"            << std::endl
                              << "--> ";
                    std::cin >> choice;
                    if (choice < 1 || choice > 5)
                    {
                        std::cout << std::endl << "Invalid choice" << std::endl;
                        continue;
                    }
                    if (choice == 1)
                        Library::loanBook(idMember,Library::getBookId());
                    else if (choice == 2)
                    {
                        std::string title = Library::getInfo("Title ? --> ");
                        for (int i = 0; i < m_shelf->currentId(); ++i)
                            if (m_shelf->book(i)->title() == title)
                                Library::loanBook(idMember,i);
                    }
                    else if (choice == 3)
                    {
                        Author author = Library::getAuthor();
                        for (int i = 0; i < m_shelf->currentId(); ++i)
                            if (m_shelf->book(i)->author() == author)
                                Library::loanBook(idMember,i);
                    }
                    else if (choice == 4)
                    {
                        std::string type = Library::getInfo("Type ? --> ");
                        for (int i = 0; i < m_shelf->currentId(); ++i)
                            if (m_shelf->book(i)->type() == type)
                                Library::loanBook(idMember,i);
                    }
                    else
                        return;
                }
            }
                void Library::loanBook(unsigned int idMember, unsigned int idBook)
                {
                    m_shelf->book(idBook)->show();
                    if (Library::confirm("Are you sure to loan this book ?"))
                        m_shelf->book(idBook)->loan(idMember);
                }

            void Library::restoreBook(unsigned int i)
            {
                /* A faire !! */
            }
            void Library::editMember(unsigned int i)
            {
                std::string firstName = Library::getInfo("First Name ? --> ");
                std::string surname = Library::getInfo("Surname ? --> ");
                m_members->member(i)->edit(m_members->member(i)->getId(), firstName, surname);
            }
    void Library::showMembers(void)
    {
        m_members->show();
    }


LibraryGet.cpp
/*
    Méthodes de la classe Library qui demandent des informations à l'utilisateur
    Les noms de fonction sont assez explicites et se passent de commentaires. 
*/

#include <iostream>

#include "Library.h"

std::string Library::getInfo(std::string msg)
{
    std::string info;
    std::cout << std::endl << msg;
    std::cin >> info;
    std::cout << std::endl;
    return info;
}
Author Library::getAuthor(void)
{
    Author a;
    a.firstName = Library::getInfo("Author's First Name ? --> ");
    a.surname = Library::getInfo("Author's Surname ?    --> ");
    return a;
}
unsigned int Library::getBookId(void)
{
    int id;
    do
    {
        std::cout << std::endl << "Id ? --> ";
        std::cin >> id;
        if (id > m_shelf->currentId())
            std::cout << std::endl << "Unknow book (maximum ID is" << m_shelf->currentId() << ")" << std::endl;
    }while (id > m_shelf->currentId());
    return id;
}
unsigned int Library::getMemberId(void)
{
    int id;
    do
    {
        std::cout << std::endl << "Id ? --> ";
        std::cin >> id;
        if (id > m_members->size())
            std::cout << std::endl << "Unknow member (maximum ID is" << m_members->size() << ")" << std::endl;
    }while(id > m_members->size());
    return id;
}
bool Library::confirm(std::string msg)
{
    std::string choice;
    do
    {
        std::cout << std::endl << msg << " Yes/No --> ";
        std::cin >> choice;
        if (choice != "Yes" && choice != "yes" && choice != "No" && choice != "no")
            std::cout << std::endl << "Invalid choice (anwsers are 'Yes' and 'No')" << std::endl;
    }
    while (choice != "Yes" && choice != "yes" && choice != "No" && choice != "no");
    if (choice == "Yes" || choice == "yes")
        return true;
    return false;
}


Voila ! J'essaierai de mettre les sources en ligne ainsi que l'exécutable. ^^

Edit : J'oubliais une petite bdd pour tester tout ça. ;)

book.txt
5
Attaque au couteau endOfTitle Patrick Carat Philosophy 1
Trenne de Lariat Ixpross endOfTitle Agathe Chris Romance 5
Herry Petter endOfTitle Jk Ralling Novel 3
Plice endOfTitle Hercol Poriot Sci_Fi 1
Chevalier Emerida endOfTitle Anna Corbillard Unknown 2


member.txt
2
Jean Valjean 2 4 3
Hugo Poifol 0
Bla bla bla
19 juillet 2011 à 1:00:23

biblio par fender

Mes commentaires au fil de l'eau.

a- pas mal de résidus du C:
- des void entre parenthèses (pas grave),
- des retours d'int au lieu de bool/exceptions qui sont plus adaptés en C++ -- je n'ai pas cherché à vérifier si les retours étaient systématiquement testé.
- des typedef désuets

b- le passage des chaines coute cher => référence constante (je pense que le tuto en parle ; à vérifier)

c- dans le main, inutile de créer la Library sur le tas vu comme elle est utilisée.

d- main.h est un choix de nom de fichier peu équivoque ; de plus il traitre d'Author

e- destructeurs inutiles vu que tous les membres des objets sont "trivialement" destructibles.

f- le préfixe "edit" me perturbe, surtout pour un setter.
De plus, vu qu'il s'agit de classes de données, tout exposer à coup de setter+getter me gêne -> toute encapsulation est de toute façon rompue.

g- getter non const-correct

i- attention, les Book sont copiables ; est-ce vraiment ce que tu veux ? Ne s'agit-il pas d'entités ?
(j'image que cela s'applique aussi à d'autres des classes)

j- m_here ne me parle pas. Serait-ce un m_is_not_being_borrowed ?

k- tu es sûr que l'on dit "restore" quand on rend des livres en anglais ?

l- m_loans.clear() est inutile : c'est implicite. Même commentaire pour le destructeur qui sera à préférer en version générée par défaut par le compilo.

m- pour le removeXXX, fait plutôt un find. Voire, utilise directement vector::remove
Ceci dit, en vrai, on aurait plutôt une liste d'ids (!= indices) et non de pointeurs. Ne serait-ce que pour faciliter la sérialisation.

n- le type des tailles, c'est size_t plutôt qu'unsigned

o- Plein d'indices qui voyagent. Joue avec les itérateurs plutôt.

p- Le destructeur de library détruit des trucs qui ne sont pas mis dans un état non invalide dans le constructeur. => kaboum possible.
D'ailleurs je vois plein de flux qui existent en permanence, et gérés via pointeurs. C'est un gros code smell en ce qui me concerne.
Localise!
C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
19 juillet 2011 à 10:31:14

Merci beaucoup pour tous ces commentaires, ça fait plaisir (même si jusqu'a 'p' ça fait beaucoup ^^ ).

Je vais tenter de les appliquer pour améliorer mon code, mais surtout ma manière de programmer en C++. ;)

Merci. :)

Juste une question toutefois, sur les destructeurs (remarques 'e' et 'l') : Je préfère quand même que ça soit explicite et bien tout écrire pour savoir bien ou je vais et ce que je fais, donc est-ce que c'est grave si je garde ma version des destructeurs ?

Bla bla bla
19 juillet 2011 à 10:49:28

Ca va jusqu'à p-, mais il n'y a rien de critique. :)

Ce que tu peux faire, c'est de mettre un commentaire pour dire "OK, il n'y a pas de destructeur, mais c'est normal : celui que va me générer le compilo sera meilleur que tous ceux que je pourrais écrire"
C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
19 juillet 2011 à 10:59:52

Ok merci, je vais éditer mon code précédent après avoir appliqué point par point tes remarques (même si je ne sais pas encore comment je vais faire pour ne pas "briser" l'encapsulation (remarque f), mais je me débrouillerai). ;)
Bla bla bla
19 juillet 2011 à 11:33:46

Ce point là, c'est celui sur lequel j'ai passé le moins de temps, et probablement le moins trivial de tous.
Tu es en situation où tu manipules des données, et non pas où tu as des entités qui offrent de véritables services.
C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
19 juillet 2011 à 12:24:42

Bon j'ai revue mon code histoire de faire plus générique, ça donne quelque chose comme :

main.cpp :
#include "main2.hh"

using namespace std;

int main(void)
{
   int choice=1;
   while(choice != EXIT)
   {
      choice = mainMenu();
      while(choice<MANAGEBOOK || (choice >MANAGELOAN && choice!=EXIT))
      {
         cout <<  "Faites un choix correct" << endl;
         choice = mainMenu();         
      }
      switch(choice)
      {
         case MANAGEBOOK: {
            Book book;
            manage(book); }
         break;
         case MANAGEMEMBER: {
         Member member;
            manage(member); }
         break;
         case MANAGELOAN: {
         Loan loan;
            manage(loan); }
         break;
         default:
         ;
      }
   }
   return EXIT_SUCCESS;
}
int mainMenu()
{
   const char* t[] = {"Gerer les Livres", "Gerer les Membres", "Gerer les Emprunts"};
   size_t i;
   for(i=0;i<sizeof t / sizeof *t;++i)
      cout << i+1 << "." <<   t[i] << endl;
   cout <<  "10.Sortir" << endl;
   cin >> i;
   return (int)i;
}
int menu()
{
   const char* t[] = {"Ajouter", "Supprimer", "Modifier", "Afficher", "Afficher tout"};
   size_t i;
   for(i=0;i<sizeof t / sizeof *t;++i)
      cout <<  i+1 << "." <<  t[i] << endl;
   cout <<  "9.Sauvegarder les changements" << endl;
   cout <<  "10.Sortir" << endl;
   cin >> i;
   return (int)i;
}     

int toBorrow(std::vector<Loan>& data)
{
   Book tbook;
   Member member;
   bool ok = false;
   Loan loan;
   in(loan);
   loan.ID = lastID(data);
   ifstream file("dataMember", ios::binary);        
   
   while(file.read((char*)&member, sizeof member))
      if(loan.IDMember == member.ID)
         ok=true;
   
   if(!ok)
   {
      cout <<  "Membre introuvable" << endl;
      return 0;
   }
   file.close();
   ok = false;
   vector<Book> book;
   file.open("dataBook", ios::binary);
   while(file.read((char*)&tbook, sizeof tbook))
      if(tbook.ID == loan.IDBook && tbook.state == NOT_BORROWED)
      {
         tbook.state = BORROWED;
         book.push_back(tbook);
         fstream out("dataBook", ios::binary | std::ios::in | std::ios::out | std::ios::ate);
         out.seekg(0, ios::beg);

         for(vector<Book>::iterator it = book.begin();it < book.end();it++)
            out.write((char*)&*it, sizeof *it);
         out.close();
         ok=true;
         break;
      }
      else 
         book.push_back(tbook);
   if(ok == false)
   {
      cout <<  "Impossible d'emprunter ce livre" << endl;
      return 0;
   }
   data.push_back(loan);
   saveChanges(data);
   return 1;
}

void toReturn(std::vector<Loan>& data)
{
   size_t ID = 0;
   cout <<  "Quel est l'ID du livre à rendre ?" << endl;
   cin >> ID;
   for(vector<Loan>::iterator its = data.begin();its < data.end();its++)
      if(its->IDBook == ID)
      {
         ifstream tmp("dataBook", ios::binary);
         vector<Book> book;
         Book tbook;
      while(tmp.read((char*)&tbook, sizeof tbook))
         if(tbook.ID == ID)
         {
            tbook.state = NOT_BORROWED;
            book.push_back(tbook);
            tmp.close();
            break;
         }
         else
            book.push_back(tbook);
      tmp.close();
      fstream file("dataBook", ios::binary | std::ios::in | std::ios::out | std::ios::ate);
      file.seekg(0, ios::beg);
      for(vector<Book>::iterator it = book.begin();it < book.end();it++)
         file.write((char*)&*it, sizeof *it);
      file.close();
      data.erase(its);
      saveChanges(data);
      return;
   }
   cout <<  "ID introuvable" << endl;
}
void in(Book& book)
{
   cin.ignore();
   cout << "Qui est l'auteur ?" << endl;
   cin.getline(book.autor, 50);
   cout << "Quel est le titre du livre ?"  << endl;
   cin.getline(book.title, 50);
   cout << "Quel est le genre du livre ?" << endl;
   cin.getline(book.kind, 50);
   book.state = NOT_BORROWED;
}
void in(Member& member)
{
   cout <<  "Quel est le nom du membre ?" << endl;
   cin >> member.Fname;
   cin.ignore();
   cout <<  "Quel est le prenom du membre ?" << endl;
   cin >> member.Sname;
   cin.ignore();
}
void in(Loan& loan)
{
   cout <<  "Quel est l'ID du livre ?" << endl;
   cin >> loan.IDBook;
   cin.ignore();
   cout <<  "Quel est l'ID de membre ?" << endl;
   cin >> loan.IDMember;
   cin.ignore();
}
void out(const Book& book)
{
   cout.width(11);cout << left << "Auteur"<< ":";cout.width(50); cout << right << book.autor << endl;
   cout.width(11);cout << left <<  "Titre"<< ":";cout.width(50); cout << right << book.title << endl;
   cout.width(11);cout << left << "Genre"<< ":";cout.width(50); cout << right << book.kind << endl;
   cout.width(11);cout << left << "Statue"<< ":";cout.width(50); cout << right << (book.state == BORROWED ? "Indisponible":"Libre") << endl;
   cout.width(11);cout << left << "ID"<< ":";cout.width(50); cout << right << book.ID << endl;
   getchar();
}
void out(const Member& member)
{
   cout.width(11);cout << left << "FName"<< ":";cout.width(50); cout << right << member.Fname << endl;
   cout.width(11);cout << left << "SName"<< ":";cout.width(50); cout << right << member.Sname << endl;
   cout.width(11);cout << left << "ID"<< ":";cout.width(50); cout << right << member.ID << endl;
   getchar();
}
void out(const Loan& loan)
{
   cout.width(15);cout << left << "ID du livre"<< ":";cout.width(50); cout << right << loan.IDBook << endl;
   cout.width(15);cout << left << "ID du membre"<< ":";cout.width(50); cout << right << loan.IDMember << endl;
   cout.width(15);cout << left << "ID"<< ":";cout.width(50); cout << right << loan.ID << endl;
   getchar();
}

main.hh :
#ifndef MAIN_HH
#define MAIN_HH
#include <iostream>
#include <vector>
#include <fstream>
#include <algorithm>

struct Book
{
   char     autor[50];
   char     title[50];
   char     kind[50];
   size_t   ID;
   bool    state;
};
struct Member
{
   char     Fname[50];
   char     Sname[50];
   size_t   ID;
};
struct Loan
{
   size_t   IDBook;
   size_t   IDMember;
   size_t   ID;
};

enum{MANAGEBOOK = 1, MANAGEMEMBER = 2, MANAGELOAN = 3, SAVECHANGES = 9, EXIT = 10};
enum{ADD = 1, DEL = 2, MODIF = 3, SHOW = 4, SHOWS = 5};
enum{BORROWED, NOT_BORROWED};

int      mainMenu();
  int   toBorrow(std::vector<Loan>&);
  void   toReturn(std::vector<Loan>&);
int menu();
void in(Member& member);
void in(Book& book);
void in(Loan& loan);

void out(const Book& book);
void out(const Member& member);
void out(const Loan& loan);

using namespace std;
template<class T> void add(vector<T>& vect)
{
   T data;
   in(data);
   data.ID = lastID(vect);
   vect.push_back(data);
}
template<class T> size_t lastID(vector<T>& vect)
{
   size_t i;
   vector<size_t> IDs;
   for(class vector<T>::iterator it = vect.begin();it < vect.end();it++)
      IDs.push_back(it->ID);
   for(i=0;i<vect.size() && find(IDs.begin(), IDs.end(), i) != IDs.end();++i);
   return i;
}
template<class T> void del(vector<T>& vect)
{
   size_t ID = 0;
   cout << "Quel est l'ID a supprimer ?" << endl;
   cin >> ID;
   for(typename vector<T>::iterator it = vect.begin();it < vect.end();it++)
      if(it->ID == ID)
      {
         vect.erase(it);
         return;
      }
   cout << "Impossible de supprimer";
}
template<> void del<Book>(vector<Book>& vect)
{
   size_t ID = 0;
   cout << "Quel est l'ID a supprimer ?" << endl;
   cin >> ID;
   for(vector<Book>::iterator it = vect.begin();it < vect.end();it++)
      if(it->ID == ID && it->state)
      {
         vect.erase(it);
         return;
      }
   cout << "Impossible de supprimer";
}
template<class T> void mod(vector<T>& vect)
{
   size_t ID = 0;
   cout <<  ("Quel est l'ID a modifier ?") << endl;
   cin >> ID;
   for(typename vector<T>::iterator it = vect.begin();it < vect.end();it++)
      if(it->ID == ID)
      {
         in(*it);
         it->ID = ID;
         return;
      }
   cout << "ID introuvable";
}
template<class T> void show(vector<T>& vect)
{
   size_t ID = 0;
   cout << "Quel est l'ID a afficher ?" << endl;
   cin >> ID;
   for(typename vector<T>::iterator it = vect.begin();it < vect.end();it++)
      if(it->ID == ID)
      {
         out(*it);
         return;
      }
   cout << "ID introuvable";
}
template<class T> void shows(vector<T>& vect)
{
   cin.ignore();
   for(typename vector<T>::iterator it = vect.begin();it < vect.end();it++)out(*it);
}
const char* getFile(vector<Book>& vect){return "dataBook";}
const char* getFile(vector<Member>& vect){return "dataMember";}
const char* getFile(vector<Loan>& vect){return "dataLoan";}
template<class T> bool cmpSection(const T& i,const T& k){ return i.ID < k.ID;}
template<class T> void saveChanges(vector<T>& vect)
{
   ofstream out(getFile(vect), ios::binary);
   for(typename vector<T>::iterator it = vect.begin();it < vect.end();it++)
      out.write((char*)&*it, sizeof *it);
}
template<class T> void manage(T& data)
{
   int choice = 0;
   vector<T> vect;
   ifstream file(getFile(vect), ios::binary);
   while(file.read((char*)&data, sizeof data))vect.push_back(data);
   while(choice != EXIT)
   {
      choice = menu();
      while(choice < ADD || (choice > SHOWS && choice!=EXIT && choice != SAVECHANGES))
      {
         cout << "Faites un choix correct" << endl;
         choice = menu();
      }
      switch(choice)
      {
         case ADD:
            add(vect);
         break;
         case DEL:
            del(vect);
         break;
         case MODIF:
            mod(vect);
         break;
         case SHOW:
            show(vect);
         break;
         case SHOWS:
            shows(vect);
         break;
         case SAVECHANGES:
            saveChanges(vect);
         break;
         default:
         ;
      }
   }
}

#endif


Ça à permis de réduire concidérablement le nombre de ligne, mais c'est à peu près tout.
Si quelqu'un a une remarque à faire, c'est la première fois que j'utilise les templates, j'aurais aimé avoir un retour s'il vous plaie :/
🍊 - Étudiant - Codeur en C | Zeste de Savoir apprenez avec une communauté | Articles  - ♡ Copying is an act of love.
20 juillet 2011 à 13:22:20

Sans trop entrer dans les détails:

a- char[50] est une horreur ! En C++, on utilise string.

b- Après un erase(), les itérateurs sont invalidés, fais attention quand tu les manipules.

c- Pourquoi donner des valeurs à tes types énumérés ? C'est rare d'en avoir besoin et casse le "principe" même des enums.

d- Connaître la taille d'un tableau statique via sizeof est une mauvaise idée.

e- Tu renvois des valeurs de retour mais tu ne les testes pas. Les exceptions sont mieux.

f- De nombreuses fonctions ne sont pas const-correct.

Voilà pour les grands principes. Je n'ai pas regardé la syntaxe en détail.
Co-auteur du cours de C++. ||| Posez vos questions sur le forum ||| Me contacter.
20 juillet 2011 à 14:51:43

Citation : Nanoc

a- char[50] est une horreur ! En C++, on utilise string.

Ok, je corrigerais ;)

Citation : Nanoc

b- Après un erase(), les itérateurs sont invalidés, fais attention quand tu les manipules.

Je crois avoir fais attention de toujours quitter après un erase().

Citation : Nanoc

c- Pourquoi donner des valeurs à tes types énumérés ? C'est rare d'en avoir besoin et casse le "principe" même des enums.

Aucune utilité en effet, cela n'était utile que pour SAVECHANGES et EXIT dans mon anciens code.

Citation : Nanoc

d- Connaître la taille d'un tableau statique via sizeof est une mauvaise idée.

Pourquoi ? Je le fais souvent. Pratique si on souhaite changer un peu le code.

Citation : Nanoc

e- Tu renvois des valeurs de retour mais tu ne les testes pas. Les exceptions sont mieux.

Je vais voir cela. Je sais a peu près ce que c'est mais comme les templates, se sera la première fois que je les utiliserais.

Citation : Nanoc

f- De nombreuses fonctions ne sont pas const-correct.

Ok, je vais voir cela.


Merci pour ces remarques, je les corrigerais ce soir ou dans l'après midi. :)
🍊 - Étudiant - Codeur en C | Zeste de Savoir apprenez avec une communauté | Articles  - ♡ Copying is an act of love.
20 juillet 2011 à 15:03:54

Citation : @che


Citation : Nanoc

d- Connaître la taille d'un tableau statique via sizeof est une mauvaise idée.

Pourquoi ? Je le fais souvent. Pratique si on souhaite changer un peu le code.



Parce que c'est pas typesafe.
20 juillet 2011 à 16:01:22

Citation : Goten

Citation : @che


Citation : Nanoc

d- Connaître la taille d'un tableau statique via sizeof est une mauvaise idée.

Pourquoi ? Je le fais souvent. Pratique si on souhaite changer un peu le code.


Parce que c'est pas typesafe.

Désolé, je ne comprend pourquoi :( Division d'un size_t par un autre size_t. J'avoue avoir du mal à comprendre pourquoi c'est une mauvaise pratique.
🍊 - Étudiant - Codeur en C | Zeste de Savoir apprenez avec une communauté | Articles  - ♡ Copying is an act of love.
20 juillet 2011 à 16:22:38

Oui, il faut savoir s'en servir en fait. C'est une habitude hérité du C et il faut avouer que pour un cas comme celui-ci c'est plutôt pratique.

Je changerait cela ;)
🍊 - Étudiant - Codeur en C | Zeste de Savoir apprenez avec une communauté | Articles  - ♡ Copying is an act of love.
20 juillet 2011 à 16:34:29

L'idée est que nous avons un truc typesafe en C++.
C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
21 juillet 2011 à 22:46:20

Voila j'ai tout corriger il me semble. Encore merci de vos remarques.

main.hh
#ifndef MAIN_HH
#define MAIN_HH
#include <iostream>
#include <vector>
#include <fstream>
#include <algorithm>

struct Book
{
   std::string     autor;
   std::string     title;
   std::string     kind;
   size_t   ID;
   bool    state;
};
struct Member
{
   std::string     Fname;
   std::string     Sname;
   size_t   ID;
};
struct Loan
{
   size_t   IDBook;
   size_t   IDMember;
   size_t   ID;
};

enum{MANAGEBOOK, MANAGEMEMBER, MANAGELOAN};
enum{ADD, DEL, MODIF, SHOW, SHOWS, SAVECHANGES, EXIT};
enum{BORROWED, NOT_BORROWED};

int      mainMenu();
  void   toBorrow(std::vector<Loan>&);
  void   toReturn(std::vector<Loan>&);
int menu();
void in(Member& member);
void in(Book& book);
void in(Loan& loan);

void out(const Book& book);
void out(const Member& member);
void out(const Loan& loan);

using namespace std;
template<class T> void add(vector<T>& vect)
{
   T data;
   in(data);
   data.ID = lastID(vect);
   vect.push_back(data);
}
template<class T> size_t lastID(const vector<T>& vect)
{
   size_t i;
   vector<size_t> IDs;
   for(class vector<T>::const_iterator it = vect.begin();it < vect.end();it++)
      IDs.push_back(it->ID);
   for(i=0;i<vect.size() && find(IDs.begin(), IDs.end(), i) != IDs.end();++i);
   return i;
}
template<class T> void del(vector<T>& vect)
{
   size_t ID = 0;
   cout << "Quel est l'ID a supprimer ?" << endl;
   cin >> ID;
   for(typename vector<T>::iterator it = vect.begin();it < vect.end();it++)
      if(it->ID == ID)
      {
         vect.erase(it);
         return;
      }
   cout << "Impossible de supprimer";
}
template<> void del<Book>(vector<Book>& vect)
{
   size_t ID = 0;
   cout << "Quel est l'ID a supprimer ?" << endl;
   cin >> ID;
   for(vector<Book>::iterator it = vect.begin();it < vect.end();it++)
      if(it->ID == ID && it->state)
      {
         vect.erase(it);
         return;
      }
   cout << "Impossible de supprimer";
}
template<class T> void mod(vector<T>& vect)
{
   size_t ID = 0;
   cout <<  ("Quel est l'ID a modifier ?") << endl;
   cin >> ID;
   for(typename vector<T>::iterator it = vect.begin();it < vect.end();it++)
      if(it->ID == ID)
      {
         in(*it);
         it->ID = ID;
         return;
      }
   cout << "ID introuvable";
}
template<class T> void show(const vector<T>& vect)
{
   size_t ID = 0;
   cout << "Quel est l'ID a afficher ?" << endl;
   cin >> ID;
   for(typename vector<T>::const_iterator it = vect.begin();it < vect.end();it++)
      if(it->ID == ID)
      {
         out(*it);
         return;
      }
   cout << "ID introuvable";
}
template<class T> void shows(const vector<T>& vect)
{
   cin.ignore();
   for(typename vector<T>::const_iterator it = vect.begin();it < vect.end();it++)out(*it);
}
const char* getFile(const vector<Book>& vect){return "dataBook";}
const char* getFile(const vector<Member>& vect){return "dataMember";}
const char* getFile(const vector<Loan>& vect){return "dataLoan";}
template<class T> bool cmpSection(const T& i,const T& k){ return i.ID < k.ID;}
template<class T> void saveChanges(vector<T>& vect)
{
   ofstream out(getFile(vect), ios::binary);
   for(typename vector<T>::iterator it = vect.begin();it < vect.end();it++)
      out.write((char*)&*it, sizeof *it);
}
template<class T> void manage(T& data)
{
   int choice = 0;
   vector<T> vect;
   ifstream file(getFile(vect), ios::binary);
   while(file.read((char*)&data, sizeof data))vect.push_back(data);
   while(choice != EXIT)
   {
      choice = menu();
      while(choice < ADD || (choice > SHOWS && choice!=EXIT && choice != SAVECHANGES))
      {
         cout << "Faites un choix correct" << endl;
         choice = menu();
      }
      switch(choice)
      {
         case ADD:
            add(vect);
         break;
         case DEL:
            del(vect);
         break;
         case MODIF:
            mod(vect);
         break;
         case SHOW:
            show(vect);
         break;
         case SHOWS:
            shows(vect);
         break;
         case SAVECHANGES:
            saveChanges(vect);
         break;
         default:
         ;
      }
   }
}

#endif

main.cpp
#include "main.hh"

using namespace std;

int main(void)
{
   int choice=1;
   while(choice != EXIT)
   {
      choice = mainMenu();
      while(choice<MANAGEBOOK || (choice >MANAGELOAN && choice!=EXIT))
      {
         cout <<  "Faites un choix correct" << endl;
         choice = mainMenu();         
      }
      switch(choice)
      {
         case MANAGEBOOK: {
            Book book;
            manage(book); }
         break;
         case MANAGEMEMBER: {
         Member member;
            manage(member); }
         break;
         case MANAGELOAN: {
         Loan loan;
            manage(loan); }
         break;
         default:
         ;
      }
   }
   return EXIT_SUCCESS;
}
int mainMenu()
{
   const char* t[] = {"Gerer les Livres", "Gerer les Membres", "Gerer les Emprunts"};
   size_t i;
   for(i=0;i<3;++i)
      cout << i+1 << "." <<   t[i] << endl;
   cout <<  "10.Sortir" << endl;
   cin >> i;
   return (int)i;
}
int menu()
{
   const char* t[] = {"Ajouter", "Supprimer", "Modifier", "Afficher", "Afficher tout"};
   size_t i;
   for(i=0;i<5;++i)
      cout <<  i+1 << "." <<  t[i] << endl;
   cout <<  "9.Sauvegarder les changements" << endl;
   cout <<  "10.Sortir" << endl;
   cin >> i;
   return (int)i;
}     

void toBorrow(std::vector<Loan>& data)
{
   Book tbook;
   Member member;
   bool ok = false;
   Loan loan;
   in(loan);
   loan.ID = lastID(data);
   ifstream file("dataMember", ios::binary);        
   
   while(file.read((char*)&member, sizeof member))
      if(loan.IDMember == member.ID)
         ok=true;
   
   if(!ok)
      cout <<  "Membre introuvable" << endl;

   file.close();
   ok = false;
   vector<Book> book;
   file.open("dataBook", ios::binary);
   while(file.read((char*)&tbook, sizeof tbook))
      if(tbook.ID == loan.IDBook && tbook.state == NOT_BORROWED)
      {
         tbook.state = BORROWED;
         book.push_back(tbook);
         fstream out("dataBook", ios::binary | std::ios::in | std::ios::out | std::ios::ate);
         out.seekg(0, ios::beg);

         for(vector<Book>::iterator it = book.begin();it < book.end();it++)
            out.write((char*)&*it, sizeof *it);
         out.close();
         ok=true;
         break;
      }
      else 
         book.push_back(tbook);
   if(ok == false)
      cout <<  "Impossible d'emprunter ce livre" << endl;

   data.push_back(loan);
   saveChanges(data);
}

void toReturn(std::vector<Loan>& data)
{
   size_t ID = 0;
   cout <<  "Quel est l'ID du livre à rendre ?" << endl;
   cin >> ID;
   for(vector<Loan>::iterator its = data.begin();its < data.end();its++)
      if(its->IDBook == ID)
      {
         ifstream tmp("dataBook", ios::binary);
         vector<Book> book;
         Book tbook;
      while(tmp.read((char*)&tbook, sizeof tbook))
         if(tbook.ID == ID)
         {
            tbook.state = NOT_BORROWED;
            book.push_back(tbook);
            tmp.close();
            break;
         }
         else
            book.push_back(tbook);
      tmp.close();
      fstream file("dataBook", ios::binary | std::ios::in | std::ios::out | std::ios::ate);
      file.seekg(0, ios::beg);
      for(vector<Book>::iterator it = book.begin();it < book.end();it++)
         file.write((char*)&*it, sizeof *it);
      file.close();
      data.erase(its);
      saveChanges(data);
      return;
   }
   cout <<  "ID introuvable" << endl;
}
void in(Book& book)
{
   cin.ignore();
   cout << "Qui est l'auteur ?" << endl;
   getline(cin, book.autor);
   cout << "Quel est le titre du livre ?"  << endl;
   getline(cin, book.title);
   cout << "Quel est le genre du livre ?" << endl;
   getline(cin, book.kind);
   book.state = NOT_BORROWED;
}
void in(Member& member)
{
   cout <<  "Quel est le nom du membre ?" << endl;
   cin >> member.Fname;
   cin.ignore();
   cout <<  "Quel est le prenom du membre ?" << endl;
   cin >> member.Sname;
   cin.ignore();
}
void in(Loan& loan)
{
   cout <<  "Quel est l'ID du livre ?" << endl;
   cin >> loan.IDBook;
   cin.ignore();
   cout <<  "Quel est l'ID de membre ?" << endl;
   cin >> loan.IDMember;
   cin.ignore();
}
void out(const Book& book)
{
   cout.width(11);cout << left << "Auteur"<< ":";cout.width(50); cout << right << book.autor << endl;
   cout.width(11);cout << left <<  "Titre"<< ":";cout.width(50); cout << right << book.title << endl;
   cout.width(11);cout << left << "Genre"<< ":";cout.width(50); cout << right << book.kind << endl;
   cout.width(11);cout << left << "Statue"<< ":";cout.width(50); cout << right << (book.state == BORROWED ? "Indisponible":"Libre") << endl;
   cout.width(11);cout << left << "ID"<< ":";cout.width(50); cout << right << book.ID << endl;
   getchar();
}
void out(const Member& member)
{
   cout.width(11);cout << left << "FName"<< ":";cout.width(50); cout << right << member.Fname << endl;
   cout.width(11);cout << left << "SName"<< ":";cout.width(50); cout << right << member.Sname << endl;
   cout.width(11);cout << left << "ID"<< ":";cout.width(50); cout << right << member.ID << endl;
   getchar();
}
void out(const Loan& loan)
{
   cout.width(15);cout << left << "ID du livre"<< ":";cout.width(50); cout << right << loan.IDBook << endl;
   cout.width(15);cout << left << "ID du membre"<< ":";cout.width(50); cout << right << loan.IDMember << endl;
   cout.width(15);cout << left << "ID"<< ":";cout.width(50); cout << right << loan.ID << endl;
   getchar();
}

🍊 - Étudiant - Codeur en C | Zeste de Savoir apprenez avec une communauté | Articles  - ♡ Copying is an act of love.
22 juillet 2011 à 0:43:02

Il y a toujours des char* -> donc ça plante si le titre est trop long par exemple.
Co-auteur du cours de C++. ||| Posez vos questions sur le forum ||| Me contacter.
22 juillet 2011 à 1:57:47

Oups, j'étais certain de l'avoir corriger :( .
C'est chose faites maintenant.
🍊 - Étudiant - Codeur en C | Zeste de Savoir apprenez avec une communauté | Articles  - ♡ Copying is an act of love.
22 juillet 2011 à 9:17:54

Tu as oublié de mettre un #include <string> au début de ton fichier.

[Exercices] Venez vous entraîner !

× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
  • Editeur
  • Markdown