Problème lors de la lecture d'objets à partir d'un fichier en c ++

Nov 28 2020

Je fais un petit projet universitaire où je dois ajouter, éditer et rechercher des enregistrements dans / à partir d'un fichier en utilisant le concept OOP. L'ajout dans un fichier fonctionne bien, mais chaque fois que j'essaie de lire un fichier, il imprime dans des textes illisibles. Voici le code complet et la sortie. main.cpp

#include <iostream>
#include <cstdlib>
#include <fstream>
#define MIN 20
#define MAX 100
#include "student.h"

using namespace std;

void add_student();
void edit_student();
void search_student();
void addToFile(const Student&);
Student* fetchFromFile();
int getFileSize();
void updateFile(Student*);

// Student stud[MAX];
int main()
{
  int choice;
  system("cls");                                                  
  system("Color B0");
  while(1)
  {                                                                                            
    cout<<"\n\t\tWhat do you want to do?"<<endl;
    cout<<"\t\t----------------------"<<endl;                                                 
    cout<<"\t\t1-Add student"<<endl;                                                       
    cout<<"\t\t2-Edit student"<<endl;                                                         
    cout<<"\t\t3-Search student"<<endl;                                                   
    cout<<"\t\t4-Quit Program"<<endl;                                                              
    cout<<"\t\t----------------------"<<endl;            
    cout<<"Enter your choice: ";                           
    cin>>choice;                                           
    switch(choice)                                         
    {
      case 1:
        add_student(); //calling add_student function to add records.
        break;
      case 2:
        edit_student();
        break;
      case 3:
        search_student();
        break;
      case 4:
        return 0;
        break;
      default:
        cout<<"Invalid choice";
        break;
    }
}
  return 0;
}

int Student::id = getFileSize() - 1; //Initialize id equals to size of file

// setData function of class Student definition
void Student :: setData()
{
  // taking input from user
  cout<<"Enter student roll no in format(1XXX): ";
  cin>>roll;
  cout<<"Enter student name: ";
  cin>>name;
  cout<<"Enter stduent date of birth(dd/mm/yy): ";
  cin>>dob;
  cout<<"Enter stduent phone no: ";
  cin>>phone;
  cout<<"Enter student address: ";
  cin>>address;
  stdId = Student::id;
}

void Student :: showData()
{
  cout<<stdId<<"  ";
  cout<<roll<<"   ";
  cout<<name<<"     ";
  cout<<dob<<"\t";
  cout<<phone<<"   ";
  cout<<address<<"\n\n";
}

const int Student :: getRoll()
{
  return roll;
}

Student& Student::operator = (const Student& newObj)
{
  stdId = newObj.stdId;
  roll = newObj.roll;
  name = newObj.name;
  dob = newObj.dob;
  phone = newObj.phone;
  address = newObj.address;
  return *this;
}

void add_student()
{
  Student stud;
  Student::incrementId();
  stud.setData();
  addToFile(stud); //adding records to file
  system("CLS");
  cout<<endl;
  cout<<"--------------------------------------------------------------------------------"<<endl;
  cout<<"---------------------------Student updated record Table---------------------------------"<<endl;
  cout<<"--------------------------------------------------------------------------------"<<endl;
  cout<<"ID      "<<"Roll      "<<"Name      "<<"DOB      "<<"Phone no         "<<"Address\n\n";
  cout<<"--------------------------------------------------------------------------------"<<endl;

  Student* student = fetchFromFile(); //getting records from file in array of objects
  int length = getFileSize(); //getting length of array of objects

  for(int i=0; i<(length-1); i++)
  {
    student[i].showData(); //showing all the data
  }

  cout<<"--------------------------------------------------------------------------------"<<endl;
  cout<<"---------------------------------FINISH-----------------------------------------"<<endl;
  cout<<"--------------------------------------------------------------------------------"<<endl;
  cout<<"You want to add more?(Y/n):  ";
  char c;
  cin>>c;
  if(c=='y' || c=='Y')
  {
    add_student();
  }
  else{
    system("pause");
  }
}

void edit_student(){
  //Showing existing record first before editing
  cout<<endl;
  cout<<"--------------------------------------------------------------------------------"<<endl;
  cout<<"---------------------------Student Existing record Table---------------------------------"<<endl;
  cout<<"--------------------------------------------------------------------------------"<<endl;
  cout<<"ID   "<<"Roll   "<<"Name      "<<"DOB      "<<"Phone no         "<<"Address\n\n";
  cout<<"--------------------------------------------------------------------------------"<<endl;

  Student* student = fetchFromFile(); //fetching all records from file
  int length = getFileSize();

  for(int i=0; i<(length-1); i++)
  {
    student[i].showData();
  }
  int idnumber;
  cout<<"--------------------------------------------------------------------------------"<<endl;
  cout<<"Which ID number your want to edit: ";

  cin>>idnumber;            //Asking the user at which ID he wants to make a change.
  //checking for valid id number
  if(idnumber>length || idnumber<0)
  {
    cout<<"\nInvalid ID Number."<<endl;
  }
  //showing existing information about that specific record
  cout<<"\nExisted information about this record.\n\n";
  cout<<"--------------------------------------------------------------------------------"<<endl;
  cout<<"ID   "<<"Roll   "<<"Name      "<<"Father\tCell no.      "<<"DOB          "<<"Address\n\n";
  cout<<"--------------------------------------------------------------------------------"<<endl;
  student[idnumber].showData();
  cout<<"\n\nEnter new data for above shown record.\n\n";
  student[idnumber].setData();         //Inputting data for that specific record.
  updateFile(student);
  cout<<"\n\nRecord updated successfully."<<endl;
  cout<<endl;
  cout<<"--------------------------------------------------------------------------------"<<endl;
  cout<<"---------------------------Updated record Table---------------------------------"<<endl;
  cout<<"--------------------------------------------------------------------------------"<<endl;
  cout<<"ID   "<<"Roll   "<<"Name      "<<"DOB      "<<"Phone no         "<<"Address\n\n";
  cout<<"--------------------------------------------------------------------------------"<<endl;
  for(int i=0; i<(length-1); i++) //Showing updated record Table
  {
    student[i].showData();
  }
}

void search_student(){
  Student* student = fetchFromFile();
  int fileLenth = getFileSize() - 1;
  int searchkey;
  cout<<"Enter roll_no of student you want to search: ";
  cin>>searchkey;     //roll_no as the search key can be entered by user.
  for(int i=1; i<fileLenth; i++)
  {
    if(searchkey==student[i].getRoll()) //checking for roll no
    {
      student[i].showData();
    }
  }
  cout<<"--------------------------------------------------------------------------------"<<endl;
  cout<<"---------------------------------FINISH-----------------------------------------"<<endl;
  cout<<"--------------------------------------------------------------------------------"<<endl;
  system("pause");
}

//FILE HANDLING

void addToFile(const Student& obj)
{
  ofstream fout;
  fout.open("records.txt", std::ofstream::app | std::ofstream::binary);
  fout.write((char*)&obj, sizeof(obj));
  cout<<"Added to file successfully!"<<endl;
  fout.close();
}

Student* fetchFromFile()
{
  int i=0;
  Student obj;
  Student* returnObj = new Student[MAX];
  ifstream fin;
  fin.open("records.txt", std::ifstream::binary);
  while(!fin.eof())
  {
    fin.read((char*)&obj, sizeof(obj));
    returnObj[i] = obj;
    i++;
  }
  fin.close();
  delete[] returnObj;
  return returnObj;
}

int getFileSize()
{
  int i=0;
  Student obj;
  ifstream fin;
  fin.open("records.txt", std::ifstream::binary);
  while(!fin.eof())
  {
    fin.read((char*)&obj, sizeof(obj));
    i++;
  }
  fin.close();
  return i;
}

void updateFile(Student* student)
{
  ofstream fout;
  fout.open("records.txt", std::ofstream::binary);
  fout.write((char*)&student, sizeof(student));
  fout.close();
}

fichier d'en-tête student.h

// A student class that hold students attributes like id, name, address and class
// Object of this class will be craeted to store student details
class Student
{
  int stdId;
  int roll;
  std::string name;
  std::string dob;
  std::string phone;
  std::string address;
public:
  static int id; //we will increase 'id' whenever student is added to the record
  //Member functions declaration
  void setData(); //this function will take input from user and set the data to attributes of class
  void showData(); //This function will give student data to user when called
  static void incrementId()
  {
    id++;
  }
  const int getRoll();
  Student& operator = (const Student&);
};

Exemple de sortie 1

Lorsque j'ajoute un objet étudiant au fichier

Exemple de sortie 2

Lire tous les enregistrements du fichier

Problème 1: Affichage de la valeur de garbage de id.

Exemple de sortie 3

Ajout d'un autre objet au fichier

Exemple de sortie 4

Lecture de tous les objets du fichier

Exemple de sortie 5

Maintenant est revenu et a choisi de modifier l'enregistrement

Problème 2: voyez comment les enregistrements s'impriment sous une forme illisible.

Pourquoi cela arrive-t-il. Maintenant, si je ferme le programme et l'exécute à nouveau, il s'affiche toujours dans un texte illisible. J'espère que vous obtenez mon problème. Je veux avoir des explications détaillées à ce sujet. Aussi, si j'ai commis d'autres erreurs diverses, merci de me le faire savoir. Je vous remercie!

Réponses

2 user4581301 Nov 29 2020 at 04:48

Studentest trop compliqué à lire avec des IO non formatées comme readet write. En termes techniques, il n'est pas trivialement copiable car il contient des std::strings et stringn'est pas trivialement copiable.

La chose la plus simple à faire est d'abandonner readet write. La plupart de vos données sont des données de type chaîne, donc écrivez <<, >>surchargez Studentet stockez tout sous forme de texte.

    friend std::ostream & operator<<(std::ostream & out, 
                                     const Student & stu) 
    { 
        out << stu.stdId << ',' <<stu.roll << ','<< stu.name... <<'\n'; 
        return out;
    } 

La lecture des données est un peu plus délicate

    friend std::istream & operator>>(std::istream & in, 
                                     Student & stu) 
    { 
        std::string line;
        if (std::getline(in, line))
        {
            std::stringstream strm(line);
            if (!(strm >> stu.stdId >> comma >> stu.roll >> comma) ||
                !std::getline(strm, stu.name, ',') ||
                !std::getline(strm, stu.dob, ',') ||
                ...))
            { // If any read failed, mark the stream as failed so the caller knows.
                out.setstate(std::ios_base::failbit);
            }
        }
        return out;
    } 
1 ytlu Nov 29 2020 at 06:47

Tout d'abord, une astuce mineure, ajoutez un constructeur vide pour la classe pour lancer tous les membres, les entiers {0} et la chaîne {}, ce qui éliminera certains gabages indésirables.

 Student::Student() :stdId(0), roll(0), name{}, dob{}, phone{}, address{} {;}

Votre problème majeur provient de la fonction fetchfomrfile () où vous supprimez le tableau Student récupéré, par conséquent, l'appelant a reçu un tableau de données non défini:

Student* fetchFromFile()
{
  int i=0;
  Student obj;
  Student* returnObj = new Student[MAX];

  //reading records from file
  fin.close();
  delete[] returnObj;// <<<< youe deleted
  return returnObj; // and return it as undefined
}

Puisque vous êtes capable de calculer la taille du fichier, je suggère dans la fonction appelant:

void search_student(){
 // Student* student = fetchFromFile();
    Student *student = new Stduent [getFileSize()];
     fecchFromFile(student); // use this array in fetch_file 
  // other things
 }

Réécrire fetchFromFile comme:

viod fetchFromFile(Stduent *ss)
{
  // read file data to array ss[i];
}