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 :

Enregistrement d'une structure dans un fichier


Sujet :

C++

  1. #1
    Membre du Club
    Homme Profil pro
    Technicien réseaux et télécoms
    Inscrit en
    Avril 2007
    Messages
    87
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : Belgique

    Informations professionnelles :
    Activité : Technicien réseaux et télécoms
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Avril 2007
    Messages : 87
    Points : 56
    Points
    56
    Par défaut Enregistrement d'une structure dans un fichier
    Bonsoir,

    Je rencontre l'erreur suivante lorsque j'essaie d'enregistrer ma structure dans un fichier :

    tribaltime.cpp:55: erreur : C2679: binary '<<' : no operator found which takes a right-hand operand of type 'TribalTime::configurationMonde' (or there is no acceptable conversion)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    void TribalTime::ajouterMonde(int numero, float vitesseMonde, float vitesseUnite)
    {
        std::ofstream fichierMondes("data/mondes.txt");
        if(fichierMondes)
        {
            struct configurationMonde mondeConfig = {numero, vitesseMonde, vitesseUnite};
     
            fichierMondes << mondeConfig;
        }
        else
        {
            QMessageBox::critical(this, tr("Erreur"), tr("Erreur lors de l'ouverture du fichier des mondes."));
        }
    }
    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
    #ifndef TRIBALTIME_H
    #define TRIBALTIME_H
     
    #include <QMainWindow>
    #include <sstream>
    #include <QtGui>
    #include <fstream>
     
    namespace Ui {
    class TribalTime;
    }
     
    class TribalTime : public QMainWindow
    {
        Q_OBJECT
     
        struct configurationMonde
        {
            int numero;
            float vitesseMonde;
            float vitesseUnite;
        };
     
    public:
        explicit TribalTime(QWidget *parent = 0);
        ~TribalTime();
       std::string getMonde() const;
       void setMonde(int m_monde);
     
    public slots:
       void aPropos();
       void ajouterMonde(int numero, float vitesseMonde, float vitesseUnite);
     
    private:
        Ui::TribalTime *ui;
        int monde;
        float vitesseMonde;
        float vitesseUnite;
        struct configurationMonde mondeConfig;
     
    };
     
    #endif // TRIBALTIME_H
    Merci d'avance !

  2. #2
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Points : 15 620
    Points
    15 620
    Par défaut
    Bonjour

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    struct configurationMonde mondeConfig = {numero, vitesseMonde, vitesseUnite};
    Ca fait quoi cette ligne pour toi ? En tout cas, c'est pas une définition de structure, ni une déclaration de variable. Et pourquoi ne pas passer directement tes variables dans le stream ?

    HS : Et j'ai du mal à voir comment tu conçois ta classe, ce qu'elle représente et ce que le service qu'elle doit rendre. Tu es sur de la conception de ta classe ?

  3. #3
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    Bonjour,

    @gbdivers: C'est bel et bien une déclaration de variable et initialisation d'objet. C'est plus verbeux que nécessaire ici, mais ça reste valide.

    @OP: L'erreur te dit simplement que le compilateur ne sait pas comment il doit faire pour mettre un objet de type configurationMonde dans un flux. As tu écrit un fonction d'insertion dans les flux pour faire ca ? Si oui tu peux la montrer (notamment les scopes qui l'entoure : namespace/classe/etc).

  4. #4
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Points : 15 620
    Points
    15 620
    Par défaut
    @Flob90
    J'avais vu le struct configurationMonde mondeConfig; dans le .h mais je voyais pas de include pour une telle structure... je pensais que c'était une erreur, j'avais pas vu la neasted struct

  5. #5
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    @gbdivers: J'avais pas vu la donnée membre nommé mondeConfig , du coup je suis pas certain que la ligne ai le comportement attendu par l'OP : masquage de la donnée membre par une variable local et pas une simple affectation. Et dans tout les cas c'est un élément de syntaxe superflus ici.

  6. #6
    Membre du Club
    Homme Profil pro
    Technicien réseaux et télécoms
    Inscrit en
    Avril 2007
    Messages
    87
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : Belgique

    Informations professionnelles :
    Activité : Technicien réseaux et télécoms
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Avril 2007
    Messages : 87
    Points : 56
    Points
    56
    Par défaut
    Citation Envoyé par Flob90 Voir le message
    Bonjour,

    @gbdivers: C'est bel et bien une déclaration de variable et initialisation d'objet. C'est plus verbeux que nécessaire ici, mais ça reste valide.

    @OP: L'erreur te dit simplement que le compilateur ne sait pas comment il doit faire pour mettre un objet de type configurationMonde dans un flux. As tu écrit un fonction d'insertion dans les flux pour faire ca ? Si oui tu peux la montrer (notamment les scopes qui l'entoure : namespace/classe/etc).
    Merci pour vos réponses !

    Non, je n'ai pas créé de telle fonction.
    Le but est de pouvoir ajouter/supprimer un monde facilement. J'avais vu en cours (de C), comment faire des listes chainées, d'où l'utilisation d'une structure pour avoir plus facile, mais j'ai un peu de mal à transposer ça en C++.

  7. #7
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Salut,
    Les listes en C++, c'est std::list.
    Pour les entrées/sorties pour ses classes, cf Comment utiliser les flux pour afficher ou saisir mes objets ?. Ceci dit, il existe des bibliothèques pour la sérialisation : cf Boost.Serialisation.

    En C, il faut effectivement répérer struct. En C++ c'est inutile:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class TribalTime : public QMainWindow
    {
        struct configurationMonde
        {
            int numero;
            float vitesseMonde;
            float vitesseUnite;
        };
     
    private:
        configurationMonde mondeConfig; // pas besoin de struct !!!
    Comme le dit Flob90, la variable locale mondeConfig masque la variable membre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    void TribalTime::ajouterMonde(int numero, float vitesseMonde, float vitesseUnite)
    {
        std::ofstream fichierMondes("data/mondes.txt");
        if(fichierMondes)
        {
            configurationMonde mondeConfig = {numero, vitesseMonde, vitesseUnite}; // ici mondeConfig  masque la variable de même nom définie pour l'objet (cf .h)
     
            fichierMondes << mondeConfig;
        }
        else
        {
            QMessageBox::critical(this, tr("Erreur"), tr("Erreur lors de l'ouverture du fichier des mondes."));
        }
    }
    Tu fais une déclaration anticipée de TribalTime dans l'espace de nom Ui. Mais tu définis la classe en dehors de cet espace de nom. Je ne pense pas que ce soit souhaité, non ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    namespace Ui {
    class TribalTime;
    }
     
    class TribalTime : public QMainWindow // Attention, ce n'est pas la classe Ui::TribalTime
    {
    Je ne connais pas Qt, mais les en-têtes suivants sont inutiles dans le fichier .h : #include <sstream> et #include <fstream>. En revanche, tu as besoin de <string>. Il faut veiller à n'inclure que ce dont on a besoin => F.A.Q. Quels fichiers d'en-tête dois-je inclure ? et suivants.

  8. #8
    Membre du Club
    Homme Profil pro
    Technicien réseaux et télécoms
    Inscrit en
    Avril 2007
    Messages
    87
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : Belgique

    Informations professionnelles :
    Activité : Technicien réseaux et télécoms
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Avril 2007
    Messages : 87
    Points : 56
    Points
    56
    Par défaut
    Merci beaucoup pour tous les conseils !

    En réalité, j'ai besoin de <sstream> pour cette fonction :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    std::string TribalTime::getMonde() const
    {
        std::ostringstream flux;
        flux << this->monde;
        return flux.str();
    }
    Tu fais une déclaration anticipée de TribalTime dans l'espace de nom Ui. Mais tu définis la classe en dehors de cet espace de nom. Je ne pense pas que ce soit souhaité, non ?
    A vrai dire, c'est QtCreator qui m'a généré les fichiers, dont cette partie.

  9. #9
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Citation Envoyé par Portus Voir le message
    En réalité, j'ai besoin de <sstream> pour cette fonction :
    Il suffit de l'inclure uniquement dans le .cpp définissant la fonction

  10. #10
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Salut,
    Citation Envoyé par 3DArchi Voir le message
    Tu fais une déclaration anticipée de TribalTime dans l'espace de nom Ui. Mais tu définis la classe en dehors de cet espace de nom. Je ne pense pas que ce soit souhaité, non ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    namespace Ui {
    class TribalTime;
    }
     
    class TribalTime : public QMainWindow // Attention, ce n'est pas la classe Ui::TribalTime
    {
    .
    Non, en fait, c'est tout à fait juste

    Ce qui se passe, c'est que Ui::TribalTime est une classe "formulaire" générée par le parsing du .ui obtenu avec Qt Designer.

    L'une des solution (hormis l'héritage public) est de placer, tout simplement, un pointeur sur la classe directement dans une classe équivalente.

    Pour éviter les dépendances plus ou moins inutiles, on peut se contenter de la déclaration anticipée et de l'inclusion du fichier d'en-tête correspondant (ici : TribalTime_ui.h) dans le fichier d'implémentation.

    Nous aurions donc:
    • TribalTime.ui : fichier "Xml" contenant la description du formulaire
    • TribalTime_ui.h : définition de Ui::TribalTime auto générée
    • TribalTime.h : définition d'une classe utilisateur (TribalTime, hors de l'espace de nom Ui) contenant les fonctions "perso"
    • TribalTime.cpp : définition des fonctions "perso"
    Ceci dit...

    @Portus ==> Tu définis une structure de type ConfigMonde de telle manière à ce qu'elle contienne en réalité trois données distinctes :
    1. numero
    2. vitesseMonde
    3. vitesseUnite
    Si le compilateur sait très bien comment envoyer un entier ou un réel dans un flux grâce à l'opérateur "<<", il ne sait par contre absolument pas comment il doit écrire cette structure dans le même flux :

    Doit-il écrire d'abord le numéro, suivi de vitesseMonde puis de vitesseUnite, ou doit il le faire dans un ordre différent

    Doit-il ajouter des informations supplémentaire, pour obtenir un résultat proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    [monde]
    numero : XXX
    vitesse monde : YY.zz
    vitesse unite : aa.bb
    ou dans un format "xml", ou autre

    Comme tu n'as rien dit au compilateur, qui n'est qu'un brave petit soldat ne prenant aucune initiative, il réagit de la seule manière "correcte" selon lui : il t'indique qu'il ne connait pas l'opérateur << pour ta structure.

    Tu dois donc veiller à fournir l'opérateur << adéquat

    Selon le cas, cela prendra soit la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    // opérateur << pour "n'importe quel flux"
    std::ostream & operator << (std::ostream & os, ConfigMonde const & cm)
    {
       // ici le format à utiliser pour écrire les données
    }
    soit la forme de

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    // opérateur << spécifique à un fichier
    std::ofstream & operator << (std::ofstream & os, ConfigMonde const & cm)
    {
       // ici le format à utiliser pour écrire les données
    }
    N'oublie pas que, si tu arrives à écrire dans un flux quelconque, il est sans doute utile de pouvoir également... lire depuis un flux similaire (car, autrement, il te sera impossible de récupérer l'information par la suite )
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  11. #11
    Membre du Club
    Homme Profil pro
    Technicien réseaux et télécoms
    Inscrit en
    Avril 2007
    Messages
    87
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : Belgique

    Informations professionnelles :
    Activité : Technicien réseaux et télécoms
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Avril 2007
    Messages : 87
    Points : 56
    Points
    56
    Par défaut
    Ok, merci beaucoup !

    J'imagine que Boost nous épargne ces procédés ?

  12. #12
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Pas vraiment. Il nous les facilite dans les cas complexes, avec boost.serialization, mais dans les cas simples comme le tien, je trouve que boost.serialization ne se justifie pas vraiment. En quelques mots :
    - Une seule fonction à écrire pour gérer sérialisation/désérialisation
    - Permet de sérialiser des structures contenant des pointeurs, en sérialisant l'objet pointé
    - Gère le fait que quand 2 pointeurs pointent sur le même objet, l'objet n'est sérialisé qu'une fois
    - Permet de sérialiser des objets de classe dérivée par l'intermédiaire d'un pointeur d'une classe de base, et de recréer l'objet du bon type à la désérialisation
    - Permet plusieurs formats de sérialisation à partir d'un même code
    - On perd le contrôle fin du format de sauvegarde (pas adapté quand on doit répondre à une format spécifique pour des raisons de compatibilité)

    Pour avoir une sérialisation "automatique" de structures, il faudrait que le langage permette la réflexion, chose que ne fait pas le C++ actuellement.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  13. #13
    Membre du Club
    Homme Profil pro
    Technicien réseaux et télécoms
    Inscrit en
    Avril 2007
    Messages
    87
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : Belgique

    Informations professionnelles :
    Activité : Technicien réseaux et télécoms
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Avril 2007
    Messages : 87
    Points : 56
    Points
    56
    Par défaut
    Ok, merci, je vais essayer avec la structure alors.

    Voilà mon TribalTime.h

    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
    #ifndef TRIBALTIME_H
    #define TRIBALTIME_H
     
    #include <QMainWindow>
    #include <boost/archive/text_oarchive.hpp>
    #include <boost/archive/text_iarchive.hpp>
     
    namespace Ui {
    class TribalTime;
    }
     
    class TribalTime : public QMainWindow
    {
        Q_OBJECT
     
        struct configMonde
        {
            int m_monde;
            float m_vitesseMonde;
            float m_vitesseUnite;
        };
     
    public:
        explicit TribalTime(QWidget *parent = 0);
        //TribalTime(int m_monde, float m_vitesseMonde, float m_vitesseUnite) : monde(m_monde), vitesseMonde(m_vitesseMonde), vitesseUnite(m_vitesseUnite) {}
        ~TribalTime();
        std::string getMonde() const;
        void setMonde(int m_monde);
        float calculCases(int x1, int y1, int x2, int y2);
     
    public slots:
        void aPropos();
        void ajouterMonde();
        void changerTemps();
     
    private:
    //    friend class boost::serialization::access;
     
    //    template<class Archive>
    //    void serialize(Archive & ar, const unsigned int version)
    //    {
    //            ar & monde;
    //            ar & vitesseMonde;
    //            ar & vitesseUnite;
    //    }
     
        Ui::TribalTime *ui;
        int monde;
        float vitesseMonde;
        float vitesseUnite;
     
    };
     
    std::ostream& operator <<(std::ostream &os, TribalTime::configMonde const &cm);
     
    #endif // TRIBALTIME_H
    Je l'ai implémentée comme ceci dans TribalTime.cpp

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    std::ofstream & operator << (std::ofstream & os, configMonde const & cm)
    {
        os << cm.m_monde << cm.m_vitesseMonde << cm.m_vitesseUnite;
        return os;
    }
    J'ai les erreurs suivantes :



    Merci d'avance !

  14. #14
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    C'est là où l'amitié est utile :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    class TribalTime : public QMainWindow
    {
       friend std::ostream& operator <<(std::ostream&, const TribalTime &);

  15. #15
    Expert éminent sénior
    Avatar de Mat.M
    Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2006
    Messages
    8 361
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2006
    Messages : 8 361
    Points : 20 381
    Points
    20 381
    Par défaut
    Salut au lieu d'utiliser std::ofstream as-tu regardé s'il n'y avait pas une classe Qt toute faite pour enregistrer des données ??
    Je ne connais pas Qt mais je suis certain que ça doit exister.
    L'avantage de std::ofstream c'est que c'est du standard C++ mais une classe du framework Qt donnera plus de souplesse

    http://qt-project.org/doc/qt-4.8/qfile.html

  16. #16
    Membre du Club
    Homme Profil pro
    Technicien réseaux et télécoms
    Inscrit en
    Avril 2007
    Messages
    87
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : Belgique

    Informations professionnelles :
    Activité : Technicien réseaux et télécoms
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Avril 2007
    Messages : 87
    Points : 56
    Points
    56
    Par défaut
    Merci à vous, je vais regarder du côté de QFile.

    J'ai avancé depuis, mais lors de l'enregistrement des données dans mon fichier j'ai toujours la valeur 1.

    J'ai un warning : tribaltime.cpp:63: avertissement : the address of 'ConfigMonde config()' will always evaluate as 'true'

    Voici mon code actuel :

    ConfigMonde.h

    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
    #ifndef CONFIGMONDE_H
    #define CONFIGMONDE_H
     
    #include <ostream>
     
    class ConfigMonde
    {
        friend std::ostream& operator <<(std::ostream&, const ConfigMonde &);
     
     
    public:
        ConfigMonde();
     
    private:
            int m_monde;
            float m_vitesseMonde;
            float m_vitesseUnite;
    };
     
    #endif // CONFIGMONDE_H
    ConfigMonde.cpp

    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
    #include "configMonde.h"
     
    ConfigMonde::ConfigMonde()
    {
        m_monde = 16;
        m_vitesseMonde = 1;
        m_vitesseUnite = 1;
    }
     
    std::ostream& operator <<(std::ostream&os, const ConfigMonde &cm)
    {
        os << cm.m_monde << cm.m_vitesseMonde << cm.m_vitesseUnite;
     
        return os;
    }
    TribalTime.h

    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
    #ifndef TRIBALTIME_H
    #define TRIBALTIME_H
     
    #include <QMainWindow>
     
    namespace Ui {
    class TribalTime;
    }
     
    class TribalTime : public QMainWindow
    {
     
        Q_OBJECT
     
    public:
        explicit TribalTime(QWidget *parent = 0);
        ~TribalTime();
        std::string getMonde() const;
        void setMonde(int m_monde);
        float calculCases(int x1, int y1, int x2, int y2);
     
    public slots:
        void aPropos();
        void ajouterMonde();
        void changerTemps();
     
    private:
        Ui::TribalTime *ui;
        int monde;
        float vitesseMonde;
        float vitesseUnite;
     
    };
     
    #endif // TRIBALTIME_H
    TribalTime.cpp

    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
    #include "tribaltime.h"
    #include "ui_tribaltime.h"
    #include "configMonde.h"
     
    #include <QtGui>
     
    #include <sstream>
    #include <fstream>
    #include <string>
    #include <iostream>
     
     
     
    TribalTime::TribalTime(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::TribalTime)
    {
        ui->setupUi(this);
     
        QStatusBar *barreEtat = statusBar();
     
        monde = 16;
        vitesseMonde = 1;
        vitesseUnite = 1;
     
        connect(ui->actionQuitter, SIGNAL(triggered()), qApp, SLOT(quit()));
        ui->actionQuitter->setShortcut(tr("Ctrl+Q"));
     
        QString qstr = QString::fromStdString("Monde " + getMonde());
        QLabel *mondeActuel = new QLabel(qstr);
        barreEtat->addWidget(mondeActuel);
     
        connect(ui->actionA_propos_de_TribalTime, SIGNAL(triggered()), this, SLOT(aPropos()));
        connect(ui->actionAjouterMonde, SIGNAL(clicked()), this, SLOT(ajouterMonde()));
        connect(ui->actionCalculerTemps, SIGNAL(clicked()), this, SLOT(changerTemps()));
    }
     
    std::string TribalTime::getMonde() const
    {
        std::ostringstream flux;
        flux << this->monde;
     
        return flux.str();
    }
     
    void TribalTime::setMonde(int m_monde)
    {
        this->monde = m_monde;
    }
     
    void TribalTime::aPropos()
    {
        QMessageBox::information(this, tr("A propos de TribalTime"), tr("Inspiré de TribalSync."));
    }
     
    void TribalTime::ajouterMonde()
    {
        std::ofstream fichierMondes("C:/Users/Simon/Desktop/tribaltime/tribaltime/data/mondes.txt");
        if(fichierMondes)
        {
            ConfigMonde config();
     
            fichierMondes << config;
     
            QMessageBox::information(this, tr("Monde ajouté"), tr("Le monde a été correctement ajouté."));
        }
        else
        {
            QMessageBox::critical(this, tr("Erreur"), tr("Erreur lors de l'ouverture du fichier des mondes."));
        }
    }
     
    float TribalTime::calculCases(int x1, int y1, int x2, int y2)
    {
        //Erreur d'une seconde pour certaines destinations
        int differenceX = abs(x1-x2);
        int differenceY = abs(y1-y2);
     
        float hypothenuse = (differenceX*differenceX) + (differenceY*differenceY);
        hypothenuse = sqrt(hypothenuse);
     
        return hypothenuse;
    }
     
    void TribalTime::changerTemps()
    {
        int xCible = ui->xVillageCible->text().toInt();
        int yCible = ui->yVillageCible->text().toInt();
        int xPersonnel = ui->xVillagePersonnel->text().toInt();
        int yPersonnel = ui->yVillagePersonnel->text().toInt();
     
        int delais = ui->delais->text().toInt();
     
        float nbCases = this->calculCases(xCible,yCible,xPersonnel,yPersonnel);
     
        std::map<int, int> tempsUnites; //temps par unité en secondes
        tempsUnites[0] = 35; //noble
        tempsUnites[1] = 18; //lancier
        tempsUnites[2] = 22; //épée
        tempsUnites[3] = 18; //hache
        tempsUnites[4] = 18; //archer
        tempsUnites[5] = 9;  //éclaireur
        tempsUnites[6] = 10; //cavalierie légère
        tempsUnites[7] = 10; //archer monté
        tempsUnites[8] = 11; //cavalerie lourde
        tempsUnites[9] = 30; //bélier
        tempsUnites[10] = 30; //catapulte
        tempsUnites[11] = 10; //paladin
     
        QDateTime heure1 = ui->dateTimeEdit->dateTime();
        QDateTime heure1Plus10 = heure1.addSecs((60*tempsUnites[ui->selectionUniteLente->currentIndex()]*nbCases)-delais);
        ui->dateTimeEdit->setDateTime(heure1Plus10);
    }
     
    TribalTime::~TribalTime()
    {
        delete ui;
    }
    J'espère être sur la bonne voie.

    Merci d'avance !

    Si vous avez d'autres remarques à faire sur le code, n'hésitez pas !

  17. #17
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Citation Envoyé par Portus Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    void TribalTime::ajouterMonde()
    {
        std::ofstream fichierMondes("C:/Users/Simon/Desktop/tribaltime/tribaltime/data/mondes.txt");
        if(fichierMondes)
        {
            ConfigMonde config();
     
            fichierMondes << config;
    C'est là qu'est ton problème, comme le dit ton warning.
    Quand tu écris ConfigMonde config();, tu penses déclarer une variable nommée config, de type ConfigMonde, construite par défaut. Mais en fait, ce que tu déclares c'est une fonction, nommée config, ne prenant pas d'arguments et retournant un objet de type ConfigMonde. Le meilleur moyen de t'en convaincre est de faire la démarche inverse : Essaye de déclarer une fonction telle que je l'ai décrite, et tu verras que tu obtiens l'écriture que tu as utilisée.

    Et donc ce que tu écris dans ton fichier, c'est l'adresse de cette fonction (je ne sais plus trop pourquoi elle est convertie en bool, mais c'est un problème annexe).

    Utilise donc ConfigMonde config; pour déclarer une variable.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  18. #18
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Salut,

    F.A.Q : Y a-t-il une différence quelconque entre MaClasse x; et MaClasse x(); ?

    Citation Envoyé par JolyLoic Voir le message
    je ne sais plus trop pourquoi elle est convertie en bool
    La conversion pointeur -> bool est la seule qui puisse être choisie lorsque les différentes surcharges l'opérateur << sont examinées. Il n'existe pas des conversions pointeur vers intégral (hormis NULL en tant que constante).

  19. #19
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Disons que l'affichage de pointeurs classiques est prévu, et que je n'ai pas pris le temps de vérifier ce qu'il en était pour les pointeurs de fonction.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  20. #20
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Les seuls pointeurs sur fonction sont ceux avec la signature pour un manipulateur sans argument :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    basic_ostream<charT,traits>& operator<< (basic_ostream<charT,traits>& (*pf)(basic_ostream<charT,traits>&));
     
    basic_ostream<charT,traits>& operator<< (basic_ios<charT,traits>& (*pf)(basic_ios<charT,traits>&));
     
    basic_ostream<charT,traits>& operator<< (ios_base& (*pf)(ios_base&));

Discussions similaires

  1. Enregistrer une structure dans un fichier txt
    Par SLF153 dans le forum MATLAB
    Réponses: 4
    Dernier message: 22/03/2011, 13h24
  2. enregistrer une structure dans un fichier
    Par Namson dans le forum C
    Réponses: 1
    Dernier message: 21/02/2009, 23h31
  3. Réponses: 17
    Dernier message: 09/03/2007, 18h13
  4. stocker une structure dans un fichier ini?
    Par Mickey.jet dans le forum C
    Réponses: 6
    Dernier message: 13/09/2006, 16h57
  5. copier une structure dans un fichier
    Par brute dans le forum MFC
    Réponses: 18
    Dernier message: 10/03/2006, 14h30

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