ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 실습8
    정리필요2 2008. 9. 1. 23:24

    #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; // 또는 char sname[MAXNAME] 사용
     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
     int namelen = (int)sname.length();     
     BinOut.write((char*) &namelen, sizeof(int));   // 4
     BinOut.write(sname.c_str(), (std::streamsize)namelen); // sname.length()
     BinOut.write((char*) &score, sizeof(float));   // 4
    }

    void StudentRecord::readFromFile(fstream& Bin)// 이진파일 읽기
    {
     int len;
     Bin.read((char*) &sno, sizeof(int));  // 4
     Bin.read((char*) &len, sizeof(int));  // 4
     char* name = new char[len+1];
     Bin.read(name, (std::streamsize)len);  // sname.length()
     name[len] = '\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) + sizeof(int) + (int)sname.length() + sizeof(score);
    }

    class KeyIndex
    {
    private:
     int key;
     int Offset;
     //int RRN;
    public:
     KeyIndex() {;}
     KeyIndex(int k, int r) {key = k, Offset = r;}
     void Set(int k, int r) {key = k, Offset = r;}
     int getKey() const {return key;}
     int getOffset() const {return Offset;}
     void readFromFile(fstream& Bin);
    };
    void KeyIndex::readFromFile(fstream& Bin)// 이진파일 읽기
    {
     // 가변길이로
     Bin.read((char*) &key, sizeof(int));  // 4
     Bin.read((char*) &Offset, 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;
    }

    int compare(int x, int y)
    {
     if(x < y) return -1;
     else if (x==y) return 0;
     else return 1;
    }

    int binarySearch(fstream& index, int key, int smax)
    {
     //KeyIndex *R = new KeyIndex[smax];
     KeyIndex R[MAXSIZE];
     for(int i=0; i<smax; i++)
      R[i].readFromFile(index);

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

     left=0;
     right=smax-1;
     
     while(left <= right)
     {
      middle = (left+right)/2;
      switch (compare(R[middle].getKey(), key))
      {
      case -1 : left = middle + 1;
       break;
      case 0 : return R[middle].getOffset(); 
      case 1 : right = middle - 1;
      }
     }
     return -1;
    }



    int main(int argc, char* argv[])
    {
     StudentRecord S[MAXSIZE], R[MAXSIZE];
     string sname; // 레코드저장할임시변수
     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++;
     }
     
     textin.close();
     fstream DataFile("student.bin", ios::in | ios::out | ios::trunc | ios::binary);
     fstream IndexFile("index.bin", ios::in | ios::out | ios::trunc | ios::binary);

     // 배열에 있는 레코드를 정렬한후 출력
     Sort<StudentRecord> sort;
     sort.bubble(S, i);

     cout << "---------[student.bin]---------" << endl;
     cout << "Sno    " <<'\t' << "Sname" << '\t' << '\t' << "Score" << endl;
     cout << "-------" <<'\t' << "-----" << '\t' << '\t' << "-----" << endl;
     for (n=0; n<i; n++)
      S[n].printRecord(cout);

     // 이진파일 생성했다.

     KeyIndex *K = new KeyIndex; // 인덱스정렬 할 배열
     for(int j=0; j<i; j++)
     {
      K->Set(S[j].getSno(), DataFile.tellp());
      S[j].writeToFile(DataFile);
      IndexFile.write((char*) K, sizeof(*K));
     }

     // 인덱스 파일 출력
     IndexFile.clear();
     IndexFile.seekg(0, ios::beg);
     cout << "---------[index.bin]---------" << endl;
     cout << "sno       " << '\t' << "address" << endl;
     cout << "----------" << '\t' << "-------" << endl;
     for (n = 0; n < i; n++)
     {
      IndexFile.read((char*) K, sizeof(*K));
      cout << K->getKey() << "\t\t" << K->getOffset() << endl;
     }

     IndexFile.clear();
     IndexFile.seekg(0, ios::beg);
     int key;
     StudentRecord s;
     char command;
     cout << "Do you want to retrieve a student record? y(es) or n(o): ";
     cin >> command;

     while (command != 'n')
     {
      IndexFile.clear();
      IndexFile.seekg(0, ios::beg);
      cout << "Enter sno : ";
      cin >> key;

      // 레코드가 인덱스 파일에 있으면 주소 값 반환, 없으면 -1 반환
      int offset = binarySearch(IndexFile, key, i);
      if (offset == -1)
       cout << "No such sno" << endl;
      else
      {
       // 데이터 파일의 get 포인터를 가져올 레코드에 위치시킴
          DataFile.seekg(offset);
       s.readFromFile(DataFile); // 레코드를 s에 갸져옴
       cout << "Sno    " <<'\t' << "Sname"
            << '\t' << '\t' << "Score" << endl;
       cout << "-------" <<'\t' << "-----" << '\t' << '\t'
                                 << "-----" << endl;
       s.printRecord(cout);
      }

      cout << "Do you want to retrieve a student record? y(es) or n(o): ";
      cin >> command;
     }

     DataFile.close();
     IndexFile.close();

     return 0;
    }

Designed by Tistory.