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++

  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 : 34
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 386
    Points : 2 640
    Points
    2 640
    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 : 40
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    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 Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

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

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Points : 20 970
    Points
    20 970
    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

  4. #4
    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 : 40
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    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;
    }

  5. #5
    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 : 34
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 386
    Points : 2 640
    Points
    2 640
    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 .

  6. #6
    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 : 40
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    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.

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

    Informations forums :
    Inscription : Avril 2005
    Messages : 41
    Points : 45
    Points
    45
    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

  8. #8
    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 : 42
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

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

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Points : 20 970
    Points
    20 970
    Par défaut
    Comme tu l'as écrit, c'est une déclaration de fonction. La fonction Donees qui retourne un std::vector<Data> et qui prend 2 paramètres.
    Il te faut définir les variables que le vecteur prend en paramètre avant. C'est une erreur classique avec cin.

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

    Informations forums :
    Inscription : Avril 2005
    Messages : 41
    Points : 45
    Points
    45
    Par défaut
    En effet gcc orends ça pour une déclaration de fonction. J'ai bien sortit mes istream_iterator de la déclaration et tout marche impec. En fait le premier appel peut être remis dedans, le second quand à lui génère cette erreur...
    Voici donc ce que je fait :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    ifstream in("myFile.qwc");
     istream_iterator<Data> last;
    vector<Data> Datas( istream_iterator<Data>(in), last );
    et là ça passe sans soucis. Encore merci pour l'aide et la technique de parcours d'un fichier

  10. #10
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2002
    Messages
    487
    Détails du profil
    Informations personnelles :
    Âge : 55
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations forums :
    Inscription : Juillet 2002
    Messages : 487
    Points : 621
    Points
    621
    Par défaut
    Heu... données, ça prend bien deux n

  11. #11
    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 : 42
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

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

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Points : 20 970
    Points
    20 970
    Par défaut
    Citation Envoyé par Tarrke
    En effet gcc orends ça pour une déclaration de fonction.
    C'est pire que ça, c'est le standard du C++ qui l'impose.

  12. #12
    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 : 34
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 386
    Points : 2 640
    Points
    2 640
    Par défaut
    Merci à tous pour la rapidité des réponses . Je vais m'atteler à bien comprendre le chapitre sur les string et sur la STL avec les vector et iterator et je testerai tout ça comme vous me l'avez proposé. Si j'ai un problème je reviendrai vous embêter ^^.

  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 : 42
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

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

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Points : 20 970
    Points
    20 970
    Par défaut
    Pas de pb, ça sera avec plaisir

  14. #14
    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 : 40
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Ah oui c'est vrai j'avais oublié cette histoire de fonction... Ce qu'on peut faire si on n'a pas envie d'écrire trois lignes de code, c'est simplement mettre une paire de parenthèses autour de l'un des deux paramètres.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    vector<Joueur> Joueurs (istream_iterator<Joueur>(fichier_in), (istream_iterator<Joueur>()));

  15. #15
    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 : 34
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 386
    Points : 2 640
    Points
    2 640
    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.

  16. #16
    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 : 34
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 386
    Points : 2 640
    Points
    2 640
    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

  17. #17
    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 : 40
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    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.

  18. #18
    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 : 34
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 386
    Points : 2 640
    Points
    2 640
    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 .

  19. #19
    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 : 40
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    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);

  20. #20
    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 : 34
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 386
    Points : 2 640
    Points
    2 640
    Par défaut
    Ah bah oui bien sûr, c'te honte ^^.

    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
    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();
        while (p1 != Joueurs.end())
        {
           cout << *p1;
           ++p1;
       }
     
        Joueur nouveauJoueur;
        cin >> nouveauJoueur.nom >> nouveauJoueur.prenom >> nouveauJoueur.pointsCours
            >> nouveauJoueur.pointsMensuels;
     
        Joueurs.push_back(nouveauJoueur);
     
        // Sauvegarde des joueurs
        ofstream fichier_out("informations.txt");
        copy(Joueurs.begin(), Joueurs.end(), ostream_iterator<Joueur>(fichier_out));
     
        system ("PAUSE");
        return 0;
    }
    Voilà ça fonctionne parfaitement !! Il n'y a plus de trucs à améliorer maintenant ? Plus de petites techniques ^^ ? En tout cas merci, je vais encore faire quelques tests afin de bien comprendre comment tout marche et relire tes posts, et après je me replongerai dans la conception de mon programme. C'est en tout cas vraiment très pratique ta méthode pour lire depuis le fichier, c'est sur que c'est bien plus commode.

    Je reviendrai si j'ai d'autres problèmes

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