ABOUT ME

-

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

    교수님의 친절한 개인지도 !! ^^*



    #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, R;

     fstream test1(argv[1]);
     fstream test2(argv[2]);

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

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

     int count1=0, count2=0;

     cout << "## test1 file ##" << endl;
     while(test1.peek() != EOF)
     {
      S.readFromFile(test1);
      S.printRecord(cout);
      count1++;
     }
     
     cout << "## test2 file ##" << endl;
     while(test2.peek() != EOF)
     {
      R.readFromFile(test2);
      R.printRecord(cout);
      count2++;
     }

     test1.clear();
     test2.clear();
     test1.seekg(0, ios::beg);
     test2.seekg(0, ios::beg);


     // 파일포인터의 위치를 잘 고려해야 한다.

     // 조교님은 seekg(-1, ios::cur); 를 이용하라 했지만 교수님은 그럴 필요없다며 while과 if, peek 만으로 해결!


     S.readFromFile(test1);
     R.readFromFile(test2); // cur 하나씩 증가


     cout << "## 합병된 파일 ##" << endl;
     while(!test1.eof() && !test2.eof()) // 둘중 먼저 끝나는 파일 까지
     {
      if(S.getSno() < R.getSno())
      {
       S.printRecord(cout); // 작은거 출력
       if(test1.peek() != EOF)
        S.readFromFile(test1); // 그다음 한 cur 증가
      }
      else
      { // S > R
       R.printRecord(cout);
       if(test2.peek() != EOF)
        R.readFromFile(test2);
      }
     }

     if(!test1.eof())
     {
      S.printRecord(cout); // 남은 파일의 포인터에 위치한 레코드 출력
      while(test1.peek() != EOF)
      { // 남은 레코드들 모두 출력
       S.readFromFile(test1);
       S.printRecord(cout);
      }
     }

     else
     {
      R.printRecord(cout);// 남은 파일의 포인터에 위치한 레코드 출력
      while(test2.peek() != EOF)
      {// 남은 레코드들 모두 출력
       S.readFromFile(test2);
       S.printRecord(cout);
      } 
     }

     test1.close();
     test2.close();

     return 0;
    }

Designed by Tistory.