ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 파일처리 실습9
    정리필요2 2008. 9. 1. 23:09

    #include <iostream>
    #include <fstream>
    #include <string>
    using namespace std;
    #define COMPARE(x, y) (((x)<(y)) ? -1:((x)==(y)) ? 0:1)
    const int MAXNAME = 20;
    const int MAXSIZE = 10;

    class StudentRecord
    {
    private:
     int sno;
     string sname;
     float score;
    public:
     StudentRecord() {;}
     StudentRecord(int no, string name, float s) {sno=no, sname=name, score=s;}
     void setSno(int no) {sno = no;}
     void setSname(string name) {sname = name;}
     void setScore(float s) {score = s;}
     int getSno() const {return sno;}
     string getSname() const {return sname;}
     float getScore() const {return score;}
     void readFromFile(fstream&);
     void writeToFile(fstream&);
     void printRecord(ostream&);
     int size();
    };
    void StudentRecord::writeToFile(fstream& BinOut)// 이진파일에 쓰기
    {
     BinOut.write((char*) &sno, sizeof(int));  // 4
     BinOut.write(sname.c_str(), MAXNAME);   // 20
     BinOut.write((char*) &score, sizeof(float));   // 4
    }

    void StudentRecord::readFromFile(fstream& Bin)// 이진파일 읽기
    {
     // 가변길이로
     Bin.read((char*) &sno, sizeof(int));  // 4
     char *name = new char[MAXNAME];
     Bin.read((char*) name, MAXNAME);   // 20
     //name[MAXNAME-1] = '\0';
     sname = name;
     Bin.read((char*) &score, sizeof(float)); // 4
    }

    void StudentRecord::printRecord(ostream&)// 화면에 출력
    {
     // 채워야 할 부분
     cout << sno <<'\t'<< sname <<'\t'<< score <<endl;
    }

    int StudentRecord::size()
    {
     return sizeof(sno) + MAXNAME + sizeof(score);
    }

    /*
    class KeyIndex
    {
    private:
     int key;
     //int Offset;
     int RRN;
    public:
     KeyIndex() {;}
     KeyIndex(int k, int r) {key = k, RRN = r;}
     void Set(int k, int r) {key = k, RRN = r;}
     int getKey() const {return key;}
     int getRRN() const {return RRN;}
     void readFromFile(fstream& Bin);
    };
    void KeyIndex::readFromFile(fstream& Bin)// 이진파일 읽기
    {
     Bin.read((char*) &key, sizeof(int));  // 4
     Bin.read((char*) &RRN, sizeof(int));  // 4
    }
    */

    template <class Type>
    class Sort
    {
    private:
     void exchange(Type &a, Type &b);
    public:
     void bubble(StudentRecord *data, int n);
    };

    template <class Type> //버블소트로 인덱스정렬
    void Sort<Type>::bubble(StudentRecord *data, int n)
    {

     int i=0, j=0;
      for(i=0; i<n; i++)
       for(j=0; j<n; j++)
        if(data[i].getSno() < data[j].getSno())
         exchange(data[i], data[j]);
    }

    template <class Type> // 교환함수
    void Sort<Type>::exchange(Type &a, Type &b)
    {
     Type c;
     c=a;
     a=b;
     b=c;
    }

    class DataFile
    {
    private:
     fstream* database;  // 저장된 데이터 파일에 대한 포인터
     int numRecord;   // 레코드 수
    public:
     DataFile() {database, numRecord = 0;}
     ~DataFile() {database->close();}
     void setDataFile(fstream& fs, int num) {database = &fs, numRecord = num;}
     void insert(StudentRecord rec);
     bool search(int sno);
     void printFile();
     void shiftRecord(int startRRN); // startRRN 위치부터 끝까지 한 레코드씩 이동
     void readByRRN(int RRN, StudentRecord& rec); // RRN에 위치한 레코드를 읽어옴
     void writeByRRN(int RRN, StudentRecord rec); // RRN 위치에  레코드 rec를 씀 
     void showRRNandOffset();
    };

    void DataFile::printFile()
    {

     if(!database->is_open())
     {
      cout << "file open fail" << endl;
      return;
     }

     database->clear();
     database->seekg(0, ios::beg);

     StudentRecord temp;
     for(int i=0; i<numRecord; i++)
     {
      temp.readFromFile(*database);
      temp.printRecord(cout);
     }
    }

    void DataFile::showRRNandOffset()
    {
     database->clear();
     database->seekg(0, ios::beg);

     StudentRecord temp;
     for(int i=0; i<numRecord; i++)
     {
      cout<< "RRN :" << i << ", Offset :" << database->tellg() << endl;
      temp.readFromFile(*database);
     
     }
    }

    void DataFile::insert(StudentRecord rec)
    {
     database->clear();
     database->seekg(0, ios::beg);

     StudentRecord *T = new StudentRecord[numRecord];
     for(int i=0; i<numRecord; i++)
      T[i].readFromFile(*database);

     if(rec.getSno() < T[0].getSno())
     {
      shiftRecord(0);
      writeByRRN(0, rec);
      numRecord++;
     }
     else if(rec.getSno() > T[numRecord-1].getSno())
     {
      writeByRRN(numRecord, rec);
      numRecord++;
     }
     else{
      for(int i=0; i<numRecord-2; i++)
      {
       if(rec.getSno() > T[i].getSno() && rec.getSno() < T[i+1].getSno())
       {
        shiftRecord(i);
        writeByRRN(i, rec);
        numRecord++;
       }
      }
     }
    }

    void DataFile::shiftRecord(int startRRN)
    {
     StudentRecord temp;
     int point = numRecord-1;
     database->clear();
     for(int i=0; point>=startRRN; point--)
     {
      readByRRN(point, temp);
      writeByRRN(point+1, temp);
     }
    }

    void DataFile::readByRRN(int RRN, StudentRecord& rec)
    {
     database->seekg(RRN*rec.size(), ios::beg);
     rec.readFromFile(*database);
    }

    void DataFile::writeByRRN(int RRN, StudentRecord rec)
    {
     database->seekg(RRN*rec.size(), ios::beg);
     rec.writeToFile(*database);
    }

    bool DataFile::search(int sno)
    {
     database->clear();
     database->seekg(0, ios::beg);

     StudentRecord *R = new StudentRecord[numRecord];
     for(int i=0; i<numRecord; i++)
      R[i].readFromFile(*database);

     int middle, left, right;
     int RRN=0;

     left=0;
     right=numRecord-1;
     
     while(left <= right)
     {
      middle = (left+right)/2;
      switch (COMPARE(R[middle].getSno(), sno))
      {
      case -1 : left = middle + 1;
       break;
      case 0 :
       cout<< "The student is in the database."<< endl;
       R[middle].printRecord(cout);
       return true; 
      case 1 : right = middle - 1;
      }
     }
     cout << "The student is not in the database."<< endl;
     return false;
    }

    int main(int argc, char* argv[])
    {
     StudentRecord S[MAXSIZE], R;

     char sname[MAXNAME]; // 레코드저장할임시변수
     int sno;
     float score;

     ifstream textin(argv[1]);

     if(!textin.is_open())
     {
      cout << "파일을 열수 없습니다. " << endl;
      return 0;
     }

     int i=0, n=0;
     // student 파일에서 레코드 읽어 배열에 저장
     while (textin.good() && textin.peek() != EOF)
     {
      textin >> sno >> sname >> score;
      textin.ignore(300, '\n');
      S[i] = StudentRecord(sno, sname, score);
      i++;
     }

     int numRecord = i; // 레코드 갯수
     
     fstream BinFile("student.bin", ios::in | ios::out | ios::trunc | ios::binary);
     
     // 배열에 있는 레코드를 정렬
     Sort<StudentRecord> sort;
     sort.bubble(S, numRecord);

     // 이진파일 생성
     for(int j=0; j<numRecord; j++)
      S[j].writeToFile(BinFile); // 이진파일에 쓰기
     
     // 이진파일 시험출력
     BinFile.clear();
     BinFile.seekg(0, ios::beg);
     for (int n=0; n<numRecord; n++)
     {
      R.readFromFile(BinFile);
      R.printRecord(cout);
     }
     
     DataFile d;
     d.setDataFile(BinFile, numRecord);
     
    /*
     StudentRecord N = StudentRecord(2002158, "KyungKyusung", 99.90);
     d.insert(N);
     d.showRRNandOffset();
     cout << endl;
     d.printFile();
    */

     int key;
     StudentRecord s;
     char command;
     cout << "Enter a choice: 1. Insert, 2. Search, 3. Print, 4. Exit:";
     cin >> command;
     

     while (command != '4')
     {
      switch(command)
      {
      case '1': // insert
      cout << "Enter a record : sno sname score :";
      cin >> sno >> sname >> score;
      s = StudentRecord(sno, sname, score);
      d.insert(s);
      break;
     
      case '2':
      cout << "Enter a student number:";
      cin >> key;
      d.search(key);
      break;

      case '3':
      d.printFile();
      break;

      default : break;
      }
      cout << "Enter a choice: 1. Insert, 2. Search, 3. Print, 4. Exit:";
      cin >> command;
     }

     return 0;
    }

Designed by Tistory.