Partage
  • Partager sur Facebook
  • Partager sur Twitter

Problème lors de lecture dans un fichier binaire

POO

Anonyme
    21 septembre 2017 à 4:19:05

    Bonjour,

    je débute en POO , et je voulais passer en pratique> un simple systeme pour sauvegarder/charger les objets dans un fichier binaire.

    Alors mon problème est le suivant: quand je vérifie les etudiants inscris ca s'affiche. mais seulement pour la premiere fois, si je ferme le programme et je retest seulement une partie s'affiche (code par exemple) aprés la troisière fois ca plante 

    #include<iostream>
    #include<fstream>
    #include<iomanip>
    #include <cstdlib>
    
    using namespace std;
    class e{
        public:
        void saisie();
        void sauver();
        void afficher1();
    
        //-----------------------------------
        private:
        string n;
        int c;
        string f;
        float m;
    
    };
    
    void e::afficher1(){
        cout << "\t" << this->c << " " << this ->n << " " << this->f << " " << this->m << endl;
    }
    void e::saisie(){
         cout << "\n\n\t Nom Complet: " ;
         getline(cin,this->n);
         cout << "\n\n\t Filiere: " ;
         getline(cin,this->f);
         cout << "\n\n\t moyenne: " ;
         cin>>this->m;
         this->c=rand() % 15885 + 11479;
    }
    void e::sauver(){ //dans le fichier
         ofstream file("data.bin",ios::binary | ios::out | ios::trunc);
         if(!file.is_open()){
         cout << "Erreur lors de sauvegarde" << endl;
         }else{
         file.write((char*)this,sizeof(e));
         file.close();
         cout <<"\n\t Etudiant inscrit avec succee"<<endl;
         }
    
    }
    void afficher(){ //charger tout les etudiants sauvés dans le fichier
         ifstream file("data.bin",ios::binary);
         if(!file.is_open()){
         cout << "Aucun etudiant inscrit pour le moment." << endl;
         }else{
         e nvt;
         while(!file.eof()){
         file.read((char*)&nvt,sizeof(e));
         if(!file.eof()){
         nvt.afficher1();
         }
         }
         file.close();
         }
    
    }
    
    int main()
    {
        e nv;
        int ch;
        do{
        system("cls");
        cout << "\n\n\t 1-Ajouter un nouveau etudiant." ;
        cout << "\n\n\t 2-Afficher les etudiants." << endl;
        cin>>ch;
        fflush(stdin);
        switch(ch){
        case 1:
        system("cls");
        nv.saisie();
        nv.sauver();
        system("pause");
        break;
        case 2:
        system("cls");
        afficher();
        system("pause");
        break;
        case 3:
        exit(0);
        break;
        }
        }while(ch!= 3);
    	return 0;
    }
    
    
    
    


    • Partager sur Facebook
    • Partager sur Twitter
      21 septembre 2017 à 8:31:38

      La vache, il a rage-quit avant qu'on lui cause o_O .

      • Partager sur Facebook
      • Partager sur Twitter

      Posez vos questions ou discutez informatique, sur le Discord NaN | Tuto : Preuve de programmes C

        21 septembre 2017 à 14:20:26

        Salut,

        Le gros problème (en plus de plein d'autres, s'entend) vient de ta fonction save : std::string est une classe qui utilise en interne un tableau de caractères alloué de manière dynamique.

        Si bien que, lorsque tu la sauvegarde en binaire de la manière dont tu t'y prend (en écrivant un nombre de bytes correspondant à la taille de ton étudiant), tout ce que tu sauve de ta std::string, c'est  -- en gros -- trois valeur numériques entières non signées:

        • une qui correspond à l'adresse mémoire à laquelle se trouve réellement la chaine de caractères au moment de l'enregistrement,
        • une qui représente la taille de la chaine de caractères et
        • une qui représente sa capacité.

        (la capacité ayant pour but d'indiquer jusqu'à quelle taille la chaine de caractères peut grandir avant qu'il ne faille envisager d'allouer plus d'espace pour celle-ci).

        Evidemment, une fois que tu as quitté ton application,  le bloc mémoire qui se trouve à l'adresse indiquée est rendu au système d'exploitation qui pourra donc l'utiliser à autre chose.

        Du coup, lorsque tu va relancer ton application et que tu vas lire ton fichier, "votre correspondant n'habite plus à l'adresse indiquée" est la seule réponse que l'ordinateur pourra donner.  Et comme ca va aller chatouiller le système d'exploitation à un endroit que tu n'aurais jamais du atteindre, il va faire planter l'application pour garantir sa propre sécurité

        Si tu veux sauvegarder une chaine de caractères dans un fichier binaire, tu as intérêt à sauvegarder au minimum la taille de cette chaine de caractères (pour savoir combien tu devras en relire plus tard) ainsi que l'ensemble du texte que cette chaine représente.

        En gros, cela devrait se faire sous une forme proche de

        void writeStingInBinary(std::ostream & ofs,std::string const & str){
            ofs.write(static_cast<char*>(& n.size()), sizeof(n.size());
            ofs.write(static_cast<char*>(n.data()), n.size()* sizeof(std::string::value_type));
        }

        Et ta fonction save devrait alors ressembler à (je vais respecter l'ordre des données membres, qui pourrait être largement amélioré)

        void e::sauver() const{ // le const indique au compilateur
                                // que tu ne compte pas modifier e ici
            /* ouverture du fichier et vérifications, que je passe */
            writeStringInBinary(ofs, n);
            ofs.write(static_cast<char*>(&c),sizeof(c));
            writeStringInBinary(ofs, f);
            ofs.write(static_cast<char*>(&m), sizeof(m));
        
        }

        Evidemment, il faudra aussi corriger la fonction de lecture, car elle ne correspond plus du tout, mais ca, ce sera un autre problème ;)

        Une petite question en passant: pourquoi utiliser un fichier binaire ?

        -
        Edité par koala01 21 septembre 2017 à 14:24:00

        • Partager sur Facebook
        • Partager sur Twitter
        Ce qui se conçoit bien s'énonce clairement. Et les mots pour le dire viennent aisément.Mon nouveau livre : Coder efficacement - Bonnes pratiques et erreurs  à éviter (en C++)Avant de faire ce que tu ne pourras défaire, penses à tout ce que tu ne pourras plus faire une fois que tu l'auras fait
          21 septembre 2017 à 14:22:03

          @koala01 : le type a déjà détruit son compte, avant 8h ce matin.

          • Partager sur Facebook
          • Partager sur Twitter

          Posez vos questions ou discutez informatique, sur le Discord NaN | Tuto : Preuve de programmes C

          Problème lors de lecture dans un fichier binaire

          × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
          × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
          • Editeur
          • Markdown