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 :

[bug aléatoire] sauvegarde dans un fichier


Sujet :

C++

  1. #1
    Membre chevronné
    Avatar de poukill
    Profil pro
    Inscrit en
    Février 2006
    Messages
    2 155
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Points : 2 107
    Points
    2 107
    Par défaut [bug aléatoire] sauvegarde dans un fichier
    Bonjour à tous!
    Je travaille sur un projet d'images où mon but est que l'utilisateur puisse placer des points sur l'écran, et les sauvegarder pour ne pas perdre son travail !
    Mon programme tourne en général au début, mais plante (les points ne se chargent plus, ou bien une partie disparaissent etc...)

    Suite à vos conseils, j'ai tout recodé en C++ pour éviter le mélange C/C++ pas beau, et surtout pour éviter les pointeurs!

    Dans ce petit projet, je place des points sur l'écran, je les sauve. Je ferme. Je rouvre. Je charge. Je replace des points, et ainsi de suite.
    Ce qui m'intrigue, c'est que je ne trouve pas de lien (même en fouillant). Tout ce que j'ai décelé, c'est que mon fichier de sauvegarde était parfois degradé (c'est à dire pas dans le format attendu )

    Pour info, mes Points De Controle sont déclarés en vector <pair> dans le programme principal. Pour sauvegarder mes points, j'écris dans le fichier "config.XY" où le premier int est le nombre de points.

    Voici les sources (parties utiles...)

    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
    
    void sauvePDC (const std::vector< std::pair <int, int> >& depart, const std::vector< std::pair <int, int> >& arrivee, float coeff_mul) {
    FILE *fichier = 0;
    int a = depart.size();
     
    int *buf = newint[4*a+1];
    buf[0] =a;
    std::vector < std::pair <int, int> >::const_iterator i;
     
    for (i=depart.begin(); i < depart.end(); i++) {
       int j= std::distance(depart.begin(), i);
         buf[j+1] =static_cast<int>( floor (static_cast<float> (i->first) /coeff_mul +0.5) );
         buf[j+a+1] = static_cast<int>( floor (static_cast<float> (i->second) /coeff_mul +0.5));
    }
    for (i=arrivee.begin(); i < arrivee.end(); i++) {
       int j= std::distance(arrivee.begin(), i);
         buf[j+2*a+1] = static_cast<int>( floor (static_cast<float> (i->first) /coeff_mul +0.5) );
         buf[j+3*a+1] = static_cast<int>( floor (static_cast<float> (i->second) /coeff_mul +0.5) );
    }
    fichier = fopen("config.XY", "w+");
    if (fichier != 0) {
         fwrite(buf, sizeof(int), 4*a+1, fichier);
         fclose(fichier);
    }
    else 
    {
         std::cerr << "erreur d'ouverture du fichier" ;
         std::exit(-1);
    }
    delete [] buf;
    }
    
    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
    void chargePDC (std::vector< std::pair <int, int> >& depart, std::vector< std::pair <int, int> >& arrivee, float coeff_mul) {
    FILE* fichier = 0;
    int *buf = newint [4*NBPOINTS+1];
    // on détruit les tableaux de points
    depart.clear();
    arrivee.clear();
    fichier = fopen("config.XY", "r");
    if (fichier != 0) {
         fread(buf,sizeof(int),4*NBPOINTS+1, fichier);
         fclose(fichier);
    }
    else 
    {
         std::cerr << "erreur d'ouverture du fichier" ;
         std::exit(-1);
    } 
    int nbelem =buf[0]; // le nombre de points présents dans le fichier
    for (int i=0; i<nbelem; i++){ 
         depart.push_back( std::make_pair ( static_cast<int> (floor (static_cast<float> (buf[i+1]) * coeff_mul + 0.5) ), static_cast<int> (floor (static_cast<float> (buf[i+1 + nbelem]) * coeff_mul + 0.5) ) ) );
         arrivee.push_back( std::make_pair(static_cast<int> (floor (static_cast<float> (buf[i+1 + 2*nbelem]) * coeff_mul + 0.5) ), static_cast<int> (floor (static_cast<float> (buf[i+1 + 3*nbelem]) * coeff_mul + 0.5) ) ) );
    }
    delete[] buf;
    }
    
    main.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
    
    std::vector < std::pair <int, int> > depart, arrivee;
    
    /* Charge les points de controles*/
    if (main_disp.key == cimg_library::cimg::keyC) {
         chargePDC(depart,arrivee, coeff_mul);
         main_disp.key = 0;
    }
    /*Sauve les Points de Controle */
    if (main_disp.key == cimg_library::cimg::keyS) {
         sauvePDC (depart,arrivee, coeff_mul);
         main_disp.key = 0;
    }
    
    Ce code effectue t-il bien ce que je veux?
    Est-ce que l'écriture dans un fichier peut parfois échouer?
    Toutes vos remarques seront utiles !
    Merci à vous.

  2. #2
    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
    Pourquoi il y a du fopen, sachant que tu ne voulais pas des pointeurs ??

  3. #3
    Membre chevronné
    Avatar de poukill
    Profil pro
    Inscrit en
    Février 2006
    Messages
    2 155
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Points : 2 107
    Points
    2 107
    Par défaut
    C'est vrai, mais je voulais enlever les pointeurs là où ils pouvaient poser problèmes. Sauf contre-indication, il ne devrait pas y avoir d'erreur sur cette partie?
    Dois-je me servir des fstream comme dans la FAQ ?

  4. #4
    Membre expert
    Avatar de hiko-seijuro
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    2 011
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 2 011
    Points : 3 065
    Points
    3 065
    Par défaut
    fopen est utilisé en c mais est ce qu'il est recommandé en C++ ? je crois pas (ptet grosse annerie lol)

    vaut mieux utiliser les streams oui je penses
    Hiko-seijuro

    n'cha - hoyoyo gang

    espace perso : http://hiko-seijuro.developpez.com
    dernier tuto : Introduction à l'éditeur de texte Emacs sous linux
    consulter les faqs : http://www.developpez.com/faq
    PAS DE QUESTIONS TECHNIQUES PAR MP OU MAIL

  5. #5
    Membre chevronné
    Avatar de poukill
    Profil pro
    Inscrit en
    Février 2006
    Messages
    2 155
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Points : 2 107
    Points
    2 107
    Par défaut
    Hé bien! Je viens de terminer mes tests après recodage, et c'est nickel...
    Je sais vraiment pas ce qui posait problème dans le code ci-dessus !
    Mais en tous cas, ça fonctionne!
    Avec en plus les avantages du C++ en terme de souplesse: pas besoin de connaitre le nombre de points, etc....

    Peut-être que le C++ n'aime pas le C ! (et encore moins les fopen ! )

    Merci à tous

  6. #6
    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
    Félicitations

  7. #7
    Membre chevronné
    Avatar de poukill
    Profil pro
    Inscrit en
    Février 2006
    Messages
    2 155
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Points : 2 107
    Points
    2 107
    Par défaut
    Merci Miles!
    J'en profite pour demander une petite précision de rien du tout sur les lignes en rouge:

    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
    
    void chargePDC (std::vector< std::pair <int, int> >& depart, std::vector< std::pair <int, int> >& arrivee, float coeff_mul) {
    // on détruit les tableaux de points
    depart.clear();
    arrivee.clear();
     
    std::ifstream entreePoints ("config.cfg", std::ios::in);
    if (!entreePoints) {
         std::cerr << "le fichier n'a pas pu être ouvert. \n";
         exit(-1);
    }
    int i=0;
    int a, b, c ,d, e; // le "e" ne sert à rien
    while (entreePoints >> e >> a >> b >> c >>d) {
         std::cout << a <<' '<< b << ' ' << c << ' '<< d << std::endl;
         depart.push_back (std::make_pair (a, b) );
         arrivee.push_back (std::make_pair (c, d) );
         i++;
    }
    std::cout << std::endl;
    }
    
    Comment fait-on pour "ignorer" le premier élément.
    Je voudrai écrire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    
    while (entreePoints >> >> a >> b >> c >>d) {
    
    Est-ce possible? J'avais pensé au cin.ignore(), mais pas là je crois!

    Merci!

    EDIT: promis après je laisse le résolu, je voulais juste pas polluer le forum avec ce détail !

  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
    Non, ce n'est pas possible d'écrire cela de cette manière, le plus simple est tout de même d'utiliser la variable "e" !

  9. #9
    Membre chevronné
    Avatar de poukill
    Profil pro
    Inscrit en
    Février 2006
    Messages
    2 155
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Points : 2 107
    Points
    2 107
    Par défaut
    ah bon...
    Hé bien d'accord alors! Si je peux pas faire mieux, alors c'est bien !

    Merci Miles!

  10. #10
    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
    Si tu as un warning, fais juste un "e;" dans ton code.

  11. #11
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    394
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2003
    Messages : 394
    Points : 473
    Points
    473
    Par défaut
    C'est quand même un peu alambiqué pour sauvegarder deux tableaux de points 2D.
    Quelques petites erreurs/remarques au passage :
    - On utilise pas la comparaison (<) dans les tests de boucle avec des itérateurs.
    Ici, le code compile parce que ce sont des vecteurs, mais si tu les remplaces par des listes ce ne sera plus le cas donc ceci
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    for (i=depart.begin(); i < depart.end(); i++)
    devient cela
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    for (i=depart.begin(); i != depart.end(); i++)
    - Utiliser distance() pour retrouver la position de l'élément courant, c'est un peu compliqué pour pas grand chose. Comme tu utilises des vecteurs, tu peux carrément te passer d'iterateurs et les manipuler comme des tableau.
    Les boucles deviennent donc :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    for (unsigned int idx=0; idx < arrivee.size(); ++idx) {
      const pair<int,int>& current = arrivee[idx];
      ...
    }
    plutôt que
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    for (i=arrivee.begin(); i < arrivee.end(); i++) {   
       int std::distance(arrivee.begin(), i);
       ...
    }
    - Si tu ajoutes 0.5 à ton calcul savant sur les points avant de les sauver, il faudra sûrement retrancher 0.5 quand tu les recharges, plutôt que de rajouter 0.5 à nouveau

    - j'aurais utilisé un fichier texte pour sauver ces données, je trouve que tout passer en binaire ça n'apporte pas grand chose et ça complique un peu. Cependant, faudrait voir l'ensemble du projet pour être sûr.
    Si tu veux comparer voilà une solution écrite à la va-vite
    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
    void sauvePDC (const vector<pair <int, int> >& depart,
                   const vector< pair <int, int> >& arrivee, 
                   float coeff_mul,
                   ostream& outStream
                   ) 
    {
      assert( (depart.size() == arrivee.size()) && "Tailles de vect. ne correspondent pas");
    
      // On sauve tout dans un grand vecteur
      vector<int> vect;
      vect.reserve(depart.size() * 4);
      for (unsigned i=0; i < depart.size(); ++i)
      {
        int val1 = f(depart[i].first);
        int val2 = f(depart[i].second);
        int val1 = f(arrivee[i].first);
         int val2 = f(arrivee[i].second);
    
        vect.push_back(val1);
        vect.push_back(val2);
        vect.push_back(val3);
        vect.push_back(val4);
      }
    
      // Sauvegarde
      // Nb d'item
      outStream << depart.size() << endl;
      
      // les items
      copy(vect.begin(), vect.end(), ostream_iterator<int>(outStream, "\n"));
    }
    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
    void chargePDC (vector<pair <int, int> >& depart, 
                    std::vector<pair <int, int> >& arrivee,
                    float coeff_mul;
                    istream& inStream) 
    {
      // Clean up
      depart.clear();
      arrivee.clear();
    
      // On récup le nombre d'item
      int nbItem;
      inStream >> nbItem;
    
      // On récup les item
      for (int i=0; i < nbItem, ++i)
      {
        int val1, val2, val3, val4;
        inStream >> val1;
        inStream >> val2;
        inStream >> val3;
        inStream >> val4;
    
         /* .: Calcul sur les valeurs :. */
    
        depart.push_back(make_pair(val1, val2));
        depart.push_back(make_pair(val3, val4));
      }
    }

  12. #12
    Membre chevronné
    Avatar de poukill
    Profil pro
    Inscrit en
    Février 2006
    Messages
    2 155
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Points : 2 107
    Points
    2 107
    Par défaut
    Merci bien pour ces précisions VoidSeer!
    J'avais effectivement un doute pour la comparaison entre deux itérateurs, mais ça avait l'air de se faire!
    Je vais donc préférer le !=

    Merci.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [VB.Net] Comment sauvegarder dans un fichier XML ?
    Par totoranky dans le forum VB.NET
    Réponses: 3
    Dernier message: 16/03/2007, 11h32
  2. [VBA E] sauvegarde dans un fichier sur reseau
    Par zoumzoum59 dans le forum Macros et VBA Excel
    Réponses: 5
    Dernier message: 12/08/2006, 10h05
  3. Sauvegarder dans un fichier en C
    Par Gryzzly dans le forum C
    Réponses: 10
    Dernier message: 14/12/2005, 16h07
  4. Réponses: 2
    Dernier message: 16/06/2005, 14h48
  5. [JList] Lecture des données sauvegardées dans un fichier
    Par Myogtha dans le forum Composants
    Réponses: 7
    Dernier message: 10/06/2004, 21h05

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