IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

Problème fichier (eof())


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Rédacteur
    Avatar de Bakura
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2005
    Messages
    1 386
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 386
    Par défaut Problème fichier (eof())
    Bonjour,

    Je suis en train de développer pour moi un petit programme de gestion de tennis de table (pour compter les points). Je sais qu'il en existe déjà beaucoup mais j'ai trouvé surtout cette idée pour m'exercer, et c'est plutôt intéressant de relier mes deux passions ^^.

    Bref, j'ai commencé à faire quelques petits tests voir si j'ai la capacité de faire tout ce que je souhaite, mais je bloque sur un petit problème. "Juste pour tester", j'ai créer un fichier binaire :

    ofstream sortieFichierJoueurs ("informations.dat", ios::binary);

    puis je l'ouvre en sortie et en entrée

    fstream sortieEntreeFichierJoueurs ("informations.dat", ios::in | ios::out);

    Puis j'ai créé à l'aide d'une structure deux joueurs (la structure contient deux strings, le nom et prénom, et deux double, un nommé pointsMensuels et un pointsCours), joueur1 et joueur2 et je leur ait donné quelques informations fictives, puis j'ai écrit le tout dans le fichier :

    Joueur joueur1 = {"Tic", "Tac", 1150.0, 785.0};
    sortieEntreeFichierJoueurs.write (reinterpret_cast <const char *> (&joueur1),
    sizeof (Joueur));

    Joueur joueur2 = {"Toc", "Tic", 720.0, 745.0};
    sortieEntreeFichierJoueurs.write (reinterpret_cast <const char *> (&joueur2),
    sizeof (Joueur));

    Jusque là pas de problème. Puis j'appelle la fonction afficherListe qui prend comme argument une référence à ce fameux fichier, et j'affiche le tout :

    void afficherListe (fstream & fichierLire)
    {
    Joueur temp;

    system ("cls");
    cout << "Les joueurs possedant une fiche sont :" << endl << endl;

    fichierLire.seekg (0); // Replace le curseur de lecture au début du fichier

    fichierLire.read (reinterpret_cast <char *> (& temp),
    sizeof (Joueur));

    while (!fichierLire.eof())
    {
    cout << temp.nom << ' ' << temp.prenom << endl;
    cout << "Points mensuels (base de calcul) : " << temp.pointsMensuels << endl
    << "Points en cours : " << temp.pointsCours << endl
    << "Progression : " << temp.pointsCours - temp.pointsMensuels << endl << endl
    << "--------------" << endl << endl;

    fichierLire.read (reinterpret_cast <char *> (& temp),
    sizeof (Joueur));
    }

    cout << endl << endl;

    system ("PAUSE");
    }
    Tout ça marche parfaitement bien, ça s'affiche pile comme je veux, c'est parfait. Le seul truc, c'est que quand je reviens dans un autre menu et que je veux réafficher une seconde fois la liste des joueurs, ben c'est tout vide, tout blanc... Puis j'ai pensé à l'eof qu'il fallait réinitialiser, j'ai donc rajouter en dessous des derniers endl un fichierLire.clear(), mais le problème, c'est qu'au lieu qu'il y n'y ait aucun nom, ça plante complétement, ça sonne,...

    Je mets le code en entier en petit (il est pas complet hein, et il y a des choses qui ne devraient pas être ou elles sont, c'est juste pour tester rapidement) :

    #include <iostream>
    using std::cout;
    using std::cerr;
    using std::cin;
    using std::ios;
    using std::endl;

    #include <string>
    using std::string;

    #include <fstream>
    using std::ofstream;
    using std::ifstream;
    using std::fstream;

    struct Joueur // Défini la structure Joueur
    {
    string nom; // Le nom de famille du joueur
    string prenom; // Le prenom du joueur
    double pointsMensuels; // Les points mensuels du joueur
    double pointsCours; // Les points en cour
    };

    int menuPrincipal ();
    void gestionJoueurs (fstream &);
    void ajouterVictoire (fstream &);
    void ajouterDefaite (fstream &);
    void cloturerMois (fstream &);

    int main()
    {
    // Créé l'objet sortieFichierJoueurs comme fichier binaire
    ofstream sortieFichierJoueurs ("informations.dat", ios::binary);

    if (!sortieFichierJoueurs) // Teste l'ouverture du fichier
    {
    cerr << "Ouverture du fichier impossible.";
    exit (1);
    }

    // Ouvre le fichier en entrée et en sortie
    fstream sortieEntreeFichierJoueurs ("informations.dat", ios::in | ios::out);

    int choix; // Contient le choix de l'utilisateur
    void (* fonction [4]) (fstream &) = {gestionJoueurs, ajouterVictoire, ajouterDefaite,
    cloturerMois};

    Joueur joueur1 = {"tc", "tn", 650.0, 642.0};
    sortieEntreeFichierJoueurs.write (reinterpret_cast <const char *> (&joueur1),
    sizeof (Joueur));

    Joueur joueur2 = {"rf", "fd", 720.0, 745.0};
    sortieEntreeFichierJoueurs.write (reinterpret_cast <const char *> (&joueur2),
    sizeof (Joueur));

    while ((choix = menuPrincipal ()) != 5)
    {
    (* fonction [choix - 1]) (sortieEntreeFichierJoueurs); // Appelle la fonction correspondante
    // à l'aide des pointeurs de
    // fonctions
    }

    system("PAUSE");
    return 0;
    }

    // Fonction gestionJoueurs : permet de voir la liste des joueurs, d'ajouter un joueur, de
    // supprimer un joueur et enfin de changer le joueur actif.
    void gestionJoueurs (fstream & fichierJoueurs)
    {
    // Prototypes des fonctions. Ainsi, elles ne peuvent être utilisées par d'autres
    // fonctions du programme, mais seulement par gestionJoueurs ()
    void afficherListe (fstream &);
    //void supprimerJoueur (ofstream &);
    //void ajouterJoueur (ofstream &);

    int choix;

    do
    {
    system ("cls");
    cout << "1 - Voir la liste des joueurs"
    << "\n2 - Supprimer un joueur"
    << "\n3 - Ajouter un joueur"
    << "\n4 - Changer le joueur actif"
    << "\n5 - Revenir au menu precedent"
    << "\nVotre choix : ";
    cin >> choix;
    } while (choix < 1 || choix > 5);

    switch (choix) // Introduit un switch
    {
    case 1:
    afficherListe (fichierJoueurs);
    break;
    case 2:
    //supprimerJoueur ();
    break;
    case 3:
    //ajouterJoueur ();
    break;
    case 4:
    break;
    case 5:
    return;
    default:
    cerr << "Erreur.";
    exit (1);
    }
    }

    void afficherListe (fstream & fichierLire)
    {
    Joueur temp;

    system ("cls");
    cout << "Les joueurs possedant une fiche sont :" << endl << endl;

    fichierLire.seekg (0); // Replace le curseur de lecture au début du fichier

    fichierLire.read (reinterpret_cast <char *> (& temp),
    sizeof (Joueur));

    while (!fichierLire.eof())
    {
    cout << temp.nom << ' ' << temp.prenom << endl;
    cout << "Points mensuels (base de calcul) : " << temp.pointsMensuels << endl
    << "Points en cours : " << temp.pointsCours << endl
    << "Progression : " << temp.pointsCours - temp.pointsMensuels << endl << endl
    << "--------------" << endl << endl;

    fichierLire.read (reinterpret_cast <char *> (& temp),
    sizeof (Joueur));
    }

    cout << endl << endl;

    system ("PAUSE");
    }

    void ajouterVictoire (fstream & fichierJoueurs)
    {
    cout << "Hello.";
    }

    void ajouterDefaite (fstream & fichierJoueurs)
    {
    cout << "Hello.";
    }

    void cloturerMois (fstream & fichierJoueurs)
    {
    cout << "Hello.";
    }

    int menuPrincipal ()
    {
    int rubrique;

    do
    {
    system ("cls"); // Vide l'affichage

    cout << "1 - Gestion des joueurs"
    << "\n2 - Ajouter une victoire"
    << "\n3 - Ajouter une defaite"
    << "\n4 - Cloturer le mois"
    << "\n5 - Quitter"
    << "\nVotre choix : ";
    cin >> rubrique;
    } while (rubrique < 1 || rubrique > 5); // Vérifie le choix de l'utilisateur

    return rubrique; // Retourne le choix;
    }
    Concernant le clear, j'ai essayé de l'ajouter à plusieurs endroits mais toujours le même résultat.

  2. #2
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    Plusieurs erreurs :

    - Tu devrais fermer sortieFichierJoueurs avant de réouvrir le même fichier avec un autre flux.

    - Tu écris et lis tes données de manière brute, mais std::string ne peut pas être écrit aussi simplement. Là tu vas écrire dans ton fichier les données membres de la classe string : sûrement un entier (la taille), et une adresse mémoire (celle de la chaîne). Donc ça a très peu de chances de fonctionner.

    - Pourquoi manipuler tes informations de manière binaire ? Sous forme textuelle tu te ferais beaucoup moins ch***, et (pour les pinailleurs) tu aurais un code portable -- même si j'imagine que tu t'en fiches un peu.

    - Pourquoi trimballer un fichier en paramètre, et non un tableau de joueurs par exemple ? Typiquement tu récupères tes données au lancement du programme, et tu les écris lorsque tu quittes, mais entre les deux il vaut mieux manipuler une structure de données plus adéquates.

    - Le test !eof() est incorrect, voir la FAQ C++ pour plus de détails.

  3. #3
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    En gros voici une version plus correcte et plus simple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    // Les en-têtes...
     
    struct Joueur // Défini la structure Joueur
    {
        string nom; // Le nom de famille du joueur
        string prenom; // Le prenom du joueur
        double pointsMensuels; // Les points mensuels du joueur
        double pointsCours; // Les points en cour
    };
     
    istream& operator >>(istream& is, Joueur& j)
    {
        if (!getline(is, j.nom))
            return is;
     
        if (!getline(is, j.prenom))
            return is;
     
        return is >> j.pointsMensuels >> j.pointsCours;
    }
     
    ostream& operator <<(ostream& os, const Joueur& j)
    {
        return os << j.nom << endl
                  << j.prenom << endl
                  << j.pointsMensuels << j.pointsCours;
    }
     
    int main()
    {
        // Lecture des joueurs
        ifstream fichier_in("informations.txt");
        vector<Joueur> Joueurs(istream_iterator<Joueur>(fichier_in), istream_iterator<Joueur>());
        fichier_in.close();
     
        // ..... Traitements sur le tableau de joueurs
     
        // Sauvegarde des joueurs
        ofstream fichier_out("informations.txt");
        copy(Joueurs.begin(), Joueurs.end(), ostream_iterator<Joueur>(fichier_out));
     
        return 0;
    }

  4. #4
    Rédacteur
    Avatar de Bakura
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2005
    Messages
    1 386
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 386
    Par défaut
    Merci. J'ai pas tout tout compris, notamment ce genre de lignes :

    if (!getline(is, j.nom))
    vector<Joueur> Joueurs (istream_iterator<Joueur>(fichier_in), istream_iterator<Joueur>());

    Je vais regarder la FAQ plus en profondeur. Pour le vector ça va, j'ai commencé à bien comprendre mais les iterator j'avais encore jamais vu ça, je ferai le chapitre de mon livre dessus ^^.

    Sinon pour l'instant donc ce que tu me dis en fait c'est d'abandonné le mode binaire et de tout gérer avec le texte et de faire donc ton fameux vector qui au lancement du programme va récupérer tout ce qu'il y a dans le fichier ? Ok ça devrait être faisable ça ^^. Par contre pour les string j'ai pas très bien compris (j'ai re-compiler mon programme avec des char * et ça marche parfaitement bien, ce sont donc les string qui merdent).

    Merci dans tous les cas, je verrai ça dans la semaine et je reviendrai si j'ai un problème .

  5. #5
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    if (!getline(is, j.nom))
    getline permet de lire une ligne dans un flux et de placer le résultat dans un string.

    vector<Joueur> Joueurs (istream_iterator<Joueur>(fichier_in), istream_iterator<Joueur>());
    Là j'utilise le constructeur de vector qui prend en paramètre une paire d'itérateurs définissant le début et la fin des données à placer dedans. istream_iterator<Joueur> permet de parcourir un flux en extrayant des données de type Joueur, en utilisant la surcharge de >> définie au préalable.

    Par contre pour les string j'ai pas très bien compris (j'ai re-compiler mon programme avec des char * et ça marche parfaitement bien, ce sont donc les string qui merdent).
    Comme je te l'ai dit, tu ne pouvais pas écrire ton string directement comme tu le faisais, ça ne pouvait pas fonctionner. Plutôt que de contourner le problème (avec des char* en plus ) essaye de comprendre pourquoi cela ne marchait pas.

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    41
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 41
    Par défaut
    Je passais juste par là et j'ai trouvé cette technique pour extraire les données d'un fichier très utile. ie :
    vector<Joueur> Joueurs (istream_iterator<Joueur>(fichier_in), istream_iterator<Joueur>());
    Cependant alors que j'essayais de l'utiliser pour mes besoins propres (à savoir récupérer une liste de données dans un fichier avec leur nom et leur valeur) je tombe sur une erreure lors de l'utilisation de mon vector.
    Voici mon code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    vector<Data> Donees(istream_iterator<Data>(in), istream_iterator<Data>());
     
      vector<Data>::iterator it = Donees.begin();
      for( ; it != Donees.end(); ++it )
      {
        cout << *it << endl;
      }
    les deux opérateur >> et << sont bien surchargés en amont... Ha et mon erreure tirée du compilo :
    main.cpp: In function `int main(int, char**)':
    main.cpp:59: error: request for member `begin' in `Donees', which is of non-class type `std::vector<Data, std::allocator<Data> > ()(std::istream_iterator<Data, char, std::char_traits<char>, ptrdiff_t>, std::istream_iterator<Data, char, std::char_traits<char>, ptrdiff_t> (*)())'
    main.cpp:60: error: request for member `end' in `Donees', which is of non-class type `std::vector<Data, std::allocator<Data> > ()(std::istream_iterator<Data, char, std::char_traits<char>, ptrdiff_t>, std::istream_iterator<Data, char, std::char_traits<char>, ptrdiff_t> (*)())'
    main.cpp:54: warning: unused variable 'buff'
    make: *** [main.o] Error 1

  7. #7
    Rédacteur
    Avatar de Bakura
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2005
    Messages
    1 386
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 386
    Par défaut
    Citation Envoyé par Loulou24
    vector<Joueur> Joueurs(istream_iterator<Joueur>(fichier_in), istream_iterator<Joueur>());
    }[/code]
    Bonjour,

    Désolé de vous redéranger ^^. J'ai potasser le chapitre sur les strings et je comprend à présent ce que sont les iterator et plusieurs fonctions des strings. Et là j'ai commencé à m'attaquer au chapitre sur la STL. Et j'ai une petite question, je souhaiterai en fait classer mes joueurs. Quand j'en ajouterai de nouveaux, je souhaiterai les classer dans l'ordre, c'est à dire donc qu'il faudra peut-être tout réecrire. Seulement mon bouquin indique que les vector ne sont performants qu'en ajout en queue. Il faudra donc utiliser autre chose (j'ai vu qu'il y avait aussi dequeu et list), non ?

    EDIT : j'ai rien dit, j'avais pas vu l'excellente image de la FAQ qui dit lequel choisir.

  8. #8
    Rédacteur
    Avatar de Bakura
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2005
    Messages
    1 386
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 386
    Par défaut
    Désolé, c'est encore moi ... J'ai quelques questions :

    Je voudrais revenir sur cette ligne : vector<Joueur> Joueurs(istream_iterator<Joueur>(fichier_in), (istream_iterator<Joueur>()));

    On m'a dit plus haut qu'on initialise un vector composé de Joueurs en utilisant une paire d'itérateurs définissant le début et la fin. Mais comment le programme sait que le deuxième iterateur est celui de la fin ? Si jamais je veux copier par exemple que trois éléments ? La le deuxième est toujours la fin ? Il n'y a pas besoin de l'initialiser avec un machin.end() ? De même, tu dis qu'il utilise les deux opérateurs surchargés << et >>, mais ou dans la ligne que j'ia mis plus haut il y a << et >> ?

    Deuxième petite question j'ai essayé de lire des informations sur le fichier que j'ai écrite moi même (oui,... je n'arrive pas encore à les rentrer à même le programme ^^), mais après pour les lire ça ne marche pas. J'ai entré dans mon informations.txt Toto Tata 650 660. Donc logiquement quand le programme se lance il récupère ça et stocke dans le vector Joueurs, c'est bien ça ? Donc après si je veux extraire les données pour les afficher dans le programme, il faut que j'utilise ce même vector. Toutefois je n'arrive pas à les afficher. J'ai essayé de créer un nouvel iterateur comme ceci :

    vector <Joueur>::const_iterator p1 = Joueurs.begin();
    cout << *p1; Et donc la logiquement il devrait m'afficher Joueurs [0] soit Toto Tata 650 660 mais ça plante .

    EDIT : j'ai aussi essayé ça :
    std::ostream_iterator <Joueur> sortie (cout, " ");
    std::copy(Joueurs.begin(), Joueurs.end(), sortie);

    mais ça marche pas

    Daysolay

  9. #9
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    On m'a dit plus haut qu'on initialise un vector composé de Joueurs en utilisant une paire d'itérateurs définissant le début et la fin. Mais comment le programme sait que le deuxième iterateur est celui de la fin ? Si jamais je veux copier par exemple que trois éléments ? La le deuxième est toujours la fin ? Il n'y a pas besoin de l'initialiser avec un machin.end() ?
    En général oui, on utilise toujours les istream_iterator du début à la fin. Et std::istream_iterator<T>() représente toujours la fin, oui. Ceci-dit tu peux toujours utiliser std::advance pour aller à une position voulue, mais du coup je ne sais pas comment ça réagit avec les fichiers, puisqu'il va en même temps avancer la position courante de lecture.

    De même, tu dis qu'il utilise les deux opérateurs surchargés << et >>, mais ou dans la ligne que j'ia mis plus haut il y a << et >> ?
    istream_iterator extrait les données avec l'opérateur >>.
    De même pour ostream_iterator, qui les envoie sur le flux via l'opérateur <<.
    Bisn sûr toi tu ne le vois pas, c'est en interne tout ça.

    ... ça plante ...
    Faut voir où ça plante, bref faire un petit debuggage.
    Mais j'ai ma petite idée : si tu as repris l'opérateur >> que je t'ai donné, il utilise getline pour extraire les noms. A la première extraction il prendra donc toute la ligne, et il ne restera rien pour le reste.
    Donc :
    - Soit tu mets une information par ligne poutôt que tout sur la même
    - Soit tes noms ne peuvent pas comporter de séparateur (espace, saut de ligne, tabulation, ...) et dans ce cas il faut utiliser l'opérateur >> pour extraire les string plutôt que getline.

  10. #10
    Rédacteur
    Avatar de Bakura
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2005
    Messages
    1 386
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 386
    Par défaut
    C'est de nouveau moi J'ai commencé à appliquer ce qu'on m'a dit ici.

    J'ai encore quelques questions, et après logiquement ça sera bon, j'aurai tout ce qu'il me faut pour faire le programme

    Je poste le code en entier :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    // Définition des en-têtes
     
    #include <iostream>
    using std::cout;
    using std::cerr;
    using std::cin;
    using std::ios;
    using std::endl;
    using std::istream;
    using std::ostream;
     
    #include <string>
    using std::string;
     
    #include <fstream>
    using std::ofstream;
    using std::ifstream;
    using std::fstream;
     
    #include <vector>
    using std::vector;
     
    #include <iterator>
    using std::istream_iterator;
    using std::ostream_iterator;
     
    // Fin de définition des en-têtes
     
    struct Joueur // Défini la structure Joueur
    {
       string nom; // Le nom de famille du joueur
       string prenom; // Le prenom du joueur
       double pointsMensuels; // Les points mensuels du joueur
       double pointsCours; // Les points en cour
    };
     
    // Prototypes des fonctions
    int menuPrincipal ();
     
    template <typename T>
    void afficherListe (const vector <T> &);
     
    template <typename T>
    void gestionJoueurs (vector <T> &);
     
    template <typename T>
    void ajouterVictoire (vector <T> &);
     
    template <typename T>
    void ajouterDefaite (vector <T> &);
     
    template <typename T>
    void cloturerMois (vector <T> &);
     
    // Surcharge des operateurs
    istream & operator >>(istream& is, Joueur& j)
    {  
       return is >> j.nom >> j.prenom >> j.pointsMensuels >> j.pointsCours;
    }
     
    ostream & operator <<(ostream& os, const Joueur& j)
    {
        return os << j.nom << ' ' << j.prenom << ' '
                  << j.pointsMensuels << ' ' << j.pointsCours << endl;
    }
     
    // -----
     
    int main()
    {
       ofstream fichier ("informations.txt", ios::app);
       fichier.close();
     
       // Créé l'objet fichier_in comme fichier texte
       ifstream fichier_in ("informations.txt");
     
       if (!fichier_in) // Teste l'ouverture du fichier
       {
          cerr << "Ouverture du fichier impossible.";
          exit (1);
       }
     
       // Ecrit le contenu du fichier dans le vector Joueurs
       vector <Joueur> Joueurs(istream_iterator<Joueur>(fichier_in), (istream_iterator<Joueur>())); 
       fichier_in.close(); // Ferme le fichier
     
       int choix; // Contient le choix de l'utilisateur
       void (* fonction [4]) (vector <Joueur> &) = {gestionJoueurs, ajouterVictoire, ajouterDefaite,
                                               cloturerMois};
     
       while ((choix = menuPrincipal ()) != 5)
       {
          (* fonction [choix - 1]) (Joueurs); // Appelle la fonction correspondante
                                                                 // à l'aide des pointeurs de
                                                                 // fonctions
       }
     
       // Ouverture du fichier en sortie
       ofstream fichier_out ("informations.txt");
     
       if (!fichier_out) // Teste l'ouverture du fichier
       {
          cerr << "Ouverture du fichier impossible.";
          exit (1);
       }
     
       // Ecrit le contenu du vector Joueurs dans le fichier texte
       copy (Joueurs.begin(), Joueurs.end(), ostream_iterator<Joueur>(fichier_out));
     
       system("PAUSE");
       return 0;
    }
     
    // Fonction gestionJoueurs : permet de voir la liste des joueurs, d'ajouter un joueur, de
    // supprimer un joueur et enfin de changer le joueur actif.
    template <typename T>
    void gestionJoueurs (vector <T> & vectorJoueurs)
    {
       // Prototypes des fonctions. Ainsi, elles ne peuvent être utilisées par d'autres
       // fonctions du programme, mais seulement par gestionJoueurs ()
       //void afficherListe (const vector <T> &);
       //void supprimerJoueur (vector <T> &);
       //void ajouterJoueur (vector <T> &);
     
       int choix;
     
       do
       {
          system ("cls");
          cout << "1 - Voir la liste des joueurs"
               << "\n2 - Supprimer un joueur"
               << "\n3 - Ajouter un joueur"
               << "\n4 - Changer le joueur actif"
               << "\n5 - Revenir au menu precedent"
               << "\nVotre choix : ";
          cin >> choix;
       } while (choix < 1 || choix > 5);
     
       switch (choix) // Introduit un switch
       {
          case 1:
             afficherListe (vectorJoueurs);
             break;
          case 2:
             //supprimerJoueur ();
             break;
          case 3:
             //ajouterJoueur ();
             break;
          case 4:
             break;
          case 5:
             return;
          default:
             cerr << "Erreur.";
             exit (1);
       }
    }
     
    template <typename T>
    void afficherListe (const vector <T> & vectorJoueurs)
    {
       system ("cls");
       cout << "Les joueurs possedant une fiche sont :" << endl << endl;
     
       typename vector <T>::const_iterator p1; // Créé un iterateur
     
       if (vectorJoueurs.empty()) // Si le vector est vide
       {
          cout << "Il n'y a pas de joueurs." << endl;
          system ("PAUSE");
          return;
       }
     
       for (p1 = vectorJoueurs.begin() ; p1 != vectorJoueurs.end() ; ++p1)
       {      
          cout << p1->nom << ' ' << p1->prenom << endl
               << "Points mensuels (base de calcul) : " << p1->pointsMensuels << endl
               << "Points en cours : " << p1->pointsCours << endl
               << "Progression : " << (p1->pointsCours) - (p1->pointsMensuels) << endl << endl
               << "--------------" << endl << endl;
       }
     
       cout << endl << endl;
     
       system ("PAUSE");
    }
     
    template <typename T>
    void ajouterVictoire (vector <T> & vectorJoueurs)
    {
       cout << "Hello.";
    }
     
    template <typename T>
    void ajouterDefaite (vector <T> & vectorJoueurs)
    {
       cout << "Hello.";
    }
     
    template <typename T>
    void cloturerMois (vector <T> & vectorJoueurs)
    {
       cout << "Hello.";
    }
     
    int menuPrincipal ()
    {
       int rubrique;
     
       do
       {
          system ("cls"); // Vide l'affichage
     
          cout << "1 - Gestion des joueurs"
               << "\n2 - Ajouter une victoire"
               << "\n3 - Ajouter une defaite"
               << "\n4 - Cloturer le mois"
               << "\n5 - Quitter"
               << "\nVotre choix : ";
          cin >> rubrique;
       } while (rubrique < 1 || rubrique > 5); // Vérifie le choix de l'utilisateur
     
       return rubrique; // Retourne le choix;
    }
    1) Au début, les fonctions de Gestion de Joueurs, j'avais mis leurs prototypes à même la fonction Gestion des joueurs (ils sont en commentaire dans la fonction gestionJoueurs) de façon à ce que seule cette fonction puisse appeler ces fonctions, toutefois ça ne marche pas. Si je mets les prototypes comme les autres prototypes de fonctions (à l'exterieur de tout bloc), ça marche bien, va comprendre...

    2) NE COMPILEZ SURTOUT PAS CE PROGRAMME... En effet, il marche bien, je peux me balader dans les fonctions, les éléments dans le fichier s'affichent bien comme je veux, SEULEMENT, quand je le ferme, le PC... reboot . A deux reprises dès que j'ai quitter le programme, ça a rebooter. Ca ne m'est jamasi arrivé, généralement seul le programme se ferme, mais là tout le PC reboot... C'est très étrange...

  11. #11
    Rédacteur
    Avatar de Bakura
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2005
    Messages
    1 386
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 386
    Par défaut
    Hej !

    Bon j'ai fait un peu comme tu m'as dit, donc moi dans mon fichier je voulais qu'il y ait les quatres informations sur la même ligne comme ceci :
    Nom Prenom Points1 Points2

    Donc j'ai fait ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    istream& operator >>(istream& is, Joueur& j)
    {  
       return is >> j.nom >> j.prenom >> j.pointsMensuels >> j.pointsCours;
    }
     
    ostream& operator <<(ostream& os, const Joueur& j)
    {
        return os << j.nom << ' ' << j.prenom << ' '
                  << j.pointsMensuels << ' ' << j.pointsCours << endl;
    }
     
    int main()
    {
        // Lecture des joueurs
        ifstream fichier_in("informations.txt");
        vector<Joueur> Joueurs(istream_iterator<Joueur>(fichier_in), (istream_iterator<Joueur>()));
        fichier_in.close();
     
        // ..... Traitements sur le tableau de joueurs
        vector <Joueur>::const_iterator p1 = Joueurs.begin();
        cout << *p1;
     
        // Sauvegarde des joueurs
        ofstream fichier_out("informations.txt");
        copy(Joueurs.begin(), Joueurs.end(), ostream_iterator<Joueur>(fichier_out));
     
        system ("PAUSE");
        return 0;
    }
    Et là ça marche bien et ça arrive à lire les informations du fichier et à me les afficher comme je veux (c'est super pratique quand même, on peut tout mettre en forme avec le ostream >> ^^.

    Maintenant une autre petite question, j'espère que je te dérange pas trop ^^. J'ai déjà vu comment ça marchait si je voulais ajouter une valeur dans un vector, par exemple Joueur.push_back (1) ou avec les insert, mais dans le cas d'une structure, je fais comment ?

    Bon donc disosn que j'initialise les 4 variables, deux string et deux double, je demande : cout << "Entrez nom, prenom, points 1, points 2";
    cin >> nom >> prenom >> points1 >> points2;

    Mais après si je veux ajouter toutes ces informations dans un Joueur de Vector, je vais comment ? Je pense qu'il faut encore utiliser operateurs surchargés ?

    Dans mon bouquin il parle d'un truc comme ça :
    std::istream_iterator <int> intEntree (cin);
    int nombre1, nombre2;
    nombre1 = *intEntree;
    ++intEntree;
    nombre2 = *intEntree;

    Mais je n'arrive pas à le faire marcher pour mes structures .

  12. #12
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    C'est facile, puisque tu as déjà un opérateur >> qui fait le boulot.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Joueur NouveauJoueur;
    cin >> NouveauJoueur;
    Tableau.push_back(NouveauJoueur);

  13. #13
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Par défaut
    Tu as essayé de passer le programme au débuggeur pour voir à quel moment ta liste devenait vide ?
    Sinon, je plussoie Loulou, comme d'hab

Discussions similaires

  1. Problème de lecture de fin de fichier (eof(fichier))
    Par jailbomba dans le forum Pascal
    Réponses: 2
    Dernier message: 21/02/2007, 16h50
  2. problème fichier devpak
    Par Myra67 dans le forum Autres éditeurs
    Réponses: 3
    Dernier message: 30/06/2005, 22h26
  3. [résolution de noms] [réseau] problème fichier hosts
    Par Aldo dans le forum Administration
    Réponses: 2
    Dernier message: 11/04/2005, 21h38
  4. [Debutant(e)] Problème fichier texte et vue
    Par solenn dans le forum Eclipse Platform
    Réponses: 2
    Dernier message: 21/07/2004, 09h23
  5. modification de fichier EOF
    Par scorbo dans le forum C
    Réponses: 9
    Dernier message: 28/11/2003, 11h35

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo