Hallgatók adatainak állományba mentése és visszatöltése

Írjunk Student osztályt, amely képes elmenteni és betölteni magát! Egy állományban több Student típusú objektumot is tárolhatunk! Valósítsuk meg mind a bináris, mind a szöveges tárolást, és az utóbbit a szabványos bemeneten és kimeneten is teszteljük!

A Student osztály adattagjai az alábbiak:

class Student

{

      static const unsigned neptun_size = 7;

      char neptun[neptun_size]; // Ehelyett is jobb lenne a string, de a példa kedvéért ezt is gyakoroljuk

      unsigned mark; // Érdemjegy: az unsigned charral több baj van, mint így (minden I/O karakterként kezeli)

 

public:

      std::string name; // Ezt nem akarjuk korlátozni     

...
};


A feladatot érdemes tanulmányozni a házi feladat mentésének/betöltésének megírása előtt.



A megoldásért kattints ide!
A megoldásnál bemutatjuk a kivételkezelés lehetőségeit is. Ezt a félév első felében hagyjuk figyelmen kívül.

A Student.h állomány tartalma:

#include <string>

#include <cstring>

 

 

class Student

{

      static const unsigned neptun_size = 7;

      char neptun[neptun_size]; // Ehelyett is jobb lenne a string, de a példa kedvéért ezt is megmutatjuk

      unsigned mark; // Érdemjegy> az unsignde charral több baj van, mint így (minden I/O karakterként kezeli)

 

public:

      std::string name; // Ezt nem akarjuk korlátozni     

      Student(std::string name = "", char neptun[] ="xxxxxx", unsigned mark=1):name(name)

      {

            setNeptun(neptun);

            setMark(mark);

      }

 

 

      void setNeptun(char neptun[]);

      const char * getNeptun()const {return neptun;}

      void setMark(unsigned mark);

      unsigned char getMark()const{return mark;}

 

      // A visszatérés a ciklusba szervezhetőség miatt, ott lehet az adatfolyam állapotát vizsgálni

      std::istream& readBinary(std::istream& is);

      void writeBinary(std::ostream& os)const;

      // A visszatérés a ciklusba szervezhetőség miatt, ott lehet az adatfolyam állapotát vizsgálni

      std::istream&  readText(std::istream& is);

      void writeText(std::ostream& os)const;

};



A Student. cpp állomány tartalma:

#include "Student.h"

#include <stdexcept>

#include <iostream>

 

using namespace std;

 

 

void Student::setNeptun(char neptun[])

{

      if(strlen(neptun) == neptun_size-1)

      {

            strcpy(this->neptun, neptun);

      }

      else

      {

            // cerr << "Bad neptun format." << endl;

            throw domain_error("Bad neptun format."); // Ezt csak a félév vége felé kell tudni, addig elég a felső sor

      }

}

 

void Student::setMark(unsigned mark)

{

      if(mark > 0 && mark <=5)

      {

            this->mark = mark;

      }

      else

      {

            // cerr << "Bad mark format." << endl;

            throw domain_error("Bad mark format.");// Ezt csak a félév vége felé kell tudni, addig elég a felső sor

      }

}

 

std::istream& Student::readBinary(std::istream& is)

{

      // Figyeljük meg a "mindent vagy semmit" megközelítést:

      // csak akkor változtatjuk az objektum állapotát, ha minden sikerült.

      // Addig ideiglenes változókba olvasunk.

           

     

      // Beolvassuk a sztring hosszát

      string::size_type length;

      is.read((char*) &length, sizeof(length));

      if(!is.good())

            return is;

 

      // Beolvassuk a sztringet

      char * nameBuffer = new char [length];

      is.read(nameBuffer, length);

     

      string name (nameBuffer, length);

      delete[] nameBuffer;

 

      // Beolvassuk a neptun kódot

      char neptun[neptun_size];

      is.read(neptun, neptun_size-1);

 

      neptun[neptun_size-1]='\0';

 

      // Beolvassuk az érdemjegyet

      unsigned mark;

      is.read((char*)&mark, sizeof(mark));

     

      if(mark == 0 || mark > 5)

            is.setstate(ios::failbit);

 

 

      // Csak akkor változtatjuk meg az objektum állapotát, ha a beolvasás sikeres volt.

      // Így tartjuk fenn a konzisztenciát.

      if(is)

      {

            this->name = name;

            strcpy(this->neptun, neptun);

            this->mark = mark;

      }

      return is;

}

 

void Student::writeBinary(std::ostream& os)const

{

      // Először kiírjuk, hány karakter van, utána pedig a karakterek következnek

      string::size_type length = name.length();

 

      os.write((const char*)&length, sizeof(length));

      os.write(name.data(), length);

 

      // Neptun kiírása a nulla nélkül (ennek hossza mindig ugyanannyi, ezért nem írjuk ki

      os.write(neptun, neptun_size-1);

     

      // Kiírjuk a jegyet is

      os.write((const char *)&mark, sizeof(mark));

}

 

std::istream& Student::readText(std::istream& is)

{

      // Változók az ideiglenes adatoknak: csak akkor változtatjuk az objektum értékét, ha minden

      // beolvasás sikeres volt.

      string name;

      char neptun[neptun_size];

      unsigned mark;

 

      getline(is,name);

      is.width(neptun_size);

      is >> neptun;

 

      if(strlen(neptun) != neptun_size-1)

            is.setstate(ios::failbit);

 

      is >> mark;

 

      if(mark == 0 || mark > 5)

            is.setstate(ios::failbit);

 

     

      if(is) // Ha nem volt hiba

      {

            this->name = name;

            strcpy(this->neptun, neptun);

            this->mark = mark;

           

      }

      return is;

}

 

void Student::writeText(std::ostream& os)const

{

      os << name << endl << neptun << endl << mark;

}



A tesztkód:

#include <iostream>

#include <fstream>

#include "Student.h"

 

using namespace std;

 

int main()

{

      Student s("James Bond", "npt007", 5);

     

      try

      {

            // Kiírás tesztelése

            s.writeText(cout); cout << endl;

           

            // Beolvasás tesztelése

            cout << "Enter the name, neptun and mark, separated with <Enter> for a student: ";

            s.readText(cin);

            if(cin)

            {

                  s.writeText(cout);

                  cout << endl;

            }

            else

            {

                  cerr << "Error reading student." << endl;

            }

 

 

            // Tesztelés állományokkal

            // (a destruktor lezárja az állományt, csak akkor zárjuk le a close tagfüggvénnyel,

            // ha az állományt megakarjuk nyitni.)

 

            // 1. Kiírás bináris állományba

            ofstream outFileBinary("student.bin", ios::out|ios::binary);

            s.writeBinary(outFileBinary);

            outFileBinary.close();

 

            // 2. Beolvasás bináris állományból

            ifstream inFileBinary ("student.bin", ios::in|ios::binary);

            Student s2;

            s2.readBinary(inFileBinary);

            if(inFileBinary)

            {

                  s2.writeText(cout); cout << endl;

            }

            else

            {

                  cerr << "Error reading student." << endl;

            }

 

 

            // 3. Kiírás szöveges állományba

            ofstream outFileText("student.txt", ios::out);

            s.writeText(outFileText);

            outFileText.close();

 

            // 4. Beolvasás szöveges állományból

            ifstream inFileText("student.txt", ios::in);

            s2.readText(inFileText);

 

            if(inFileText)

            {

                  s2.writeText(cout); cout << endl;

            }

            else

            {

                  cerr << "Error reading student." << endl;

            }

 

 

 

            // 1. Több hallgató kiírása bináris állományba

            ofstream outFileBinaryStudents("students.bin", ios::out|ios::binary);

           

            for(int i=0; i<=5; i++)

            {

                  s.writeBinary(outFileBinaryStudents);               

            }

           

            outFileBinaryStudents.close();

 

            // 2. Több hallgató beolvasás bináris állományból

            ifstream inFileBinaryStudents ("students.bin", ios::in|ios::binary);

     

            // Itt kényelmes a visszatérési érték.

            while(s2.readBinary(inFileBinaryStudents))

            {

                  s2.writeText(cout); cout << endl;

            }

     

 

 

            // 3. Több hallgató kiírása szöveges állományba

            ofstream outFileTextStudents("students.txt", ios::out);

           

            for(int i=0; i<=3;i++)

            {

                  s.writeText(outFileTextStudents);

            }

 

            outFileText.close();

 

            // 4. Több hallgató beolvasása szöveges állományból

            ifstream inFileTextStudents("students.txt", ios::in);

           

            // Itt kényelmes a visszatérési érték.

            while(s2.readText(inFileTextStudents))

            {

                  s2.writeText(cout); cout << endl;

            }

 

      }

      catch(const exception& e) // Elkapjuk a kivételeket

      {

            cout << e.what() << endl;

      }

 

}





2008.01.17. 23:15:41 |  Permalink  |  Hozzászólások száma: 0  |  Tárgyszavak: Állományok kezelése


Írja meg Ön is véleményét!


Hozzászólásokat csak regisztrált, bejelentkezett felhasználóktól tudunk elfogadni!

Hozzászólások