ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • P02
    정리필요2 2008. 9. 2. 15:43

    #include <iostream>
    #include <fstream>
    #include <string>
    using namespace std;

    class node // 링크리스트 노드 클래스
    { // friend class로 StudentRecord 설정
     friend class StudentRecord;
    public:
     int sno;
     string sname;
     float score;
     node *link;
    };

    node *ptr; // 리스트 root

    class StudentRecord
    {
    private:
     int sno;
     string sname;
     float score;

    public:
     StudentRecord()
     { // 노드의 초기화
      ptr = new node;
      ptr->sno = 0;
      ptr->sname = "";
      ptr->score = 0;
      ptr->link = NULL;
     }

     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(ifstream&); // 파일에서 읽는 함수
     void printRecord(ostream&); // 레코드 출력 함수
     bool operator== (StudentRecord s); // operator == 재정의 함수
     void addback(); // 리스트 맨뒤에 새노드추가 함수
    };


    bool is_NodeNull(node *p1) // 노드가 NULL인지 검사 함수
    {
     if(p1->sno==0 && p1->sname =="" && p1->score == 0)
      return false;
     else
      return true;
    }

    void exchange(node *x, node *y) // 노드값 교환 함수
    {        
     node* temp = new node;
     // 다음노드의 포인터를 제외한 나머지 교환
     temp->sno = x->sno;
     temp->sname = x->sname;
     temp->score = x->score;
     x->sno = y->sno;
     x->sname = y->sname;
     x->score = y->score;
     y->sno = temp->sno;
     y->sname = temp->sname;
     y->score = temp->score;
    }

    void bubble(node *p) // 리스트 정렬
    {
     node *q = new node;
     q = p;
     while (q)
     {
      node *p1 = new node;
      *p1 = *q;
      while(p1)
      {
       if(p1->sno < q->sno)
        exchange(p1, q);
       p1 = p1->link;
      }
      delete p1;
     q = q->link;
     }
     p = q;
     delete q;
    }


    bool StudentRecord::operator== (StudentRecord s) // == 연산자 재정의
    {
     if(this->sno==s.sno && this->sname==s.sname && this->score==s.score)
      return true;
     else
      return false;
    }

    void StudentRecord::readFromFile(ifstream& Bin)// 이진파일 읽기
    {
     int len;
     char* name = new char[20];
     Bin.read((char*) &sno, sizeof(int));
     Bin.read((char*) &len, sizeof(int));
     Bin.read((char*) name, (std::streamsize)len);
     name[len] = '\0';
     sname = name;
     Bin.read((char*) &score, sizeof(float));
    }

    void StudentRecord::addback()
    { // 새 레코드를 리스트 맨뒤에 추가
     node *pt = new node;
     node *temp = new node;
     pt = ptr;

     temp->sno = this->sno;
     temp->sname = this->sname;
     temp->score = this->score;
     // 리스트의root인 ptr에 값이 있는지
     // 검사해 있으면 없을때 까지 리스트
     // 하위로 내려가 끝에 새노드 추가
     if(is_NodeNull(ptr))
     {
      while(pt->link)
      {
       pt = pt->link;
      }

      temp->link = NULL;
      pt->link = temp;
     }
     else
     {
      temp->link = NULL;
      ptr = temp;
     }
    }
     
    void printList(node *ptr)// 리스트를 화면에 출력
    {
     node *p1;
     p1 = ptr;
     while(p1)
     {
      cout << p1->sno <<'\t'<< p1->sname <<'\t'<< p1->score <<endl;
      p1 = p1->link;
     }

    }

    float average(node *ptr)// 리스트의 score들의 평균
    {
     node *p1;
     p1 = ptr;
     int cnt=0;
     float average=0;
     while(p1)
     {
      average += p1->score;
      p1 = p1->link;
      cnt++;
     }
     return average/cnt;

    }

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


    void writeToFile(ofstream& BinOut, node *ptr)// 리스트를 이진파일에 쓰기
    {
     node *p1; // 임시노드
     p1 = ptr;
     while(p1)
     {
      // 채워야 할 부분
      int namelen = (int)p1->sname.length();
      BinOut.write((char*) &p1->sno, sizeof(int));
      BinOut.write((char*) &namelen, sizeof(int));
      BinOut.write(p1->sname.c_str(), (std::streamsize)namelen);
      BinOut.write((char*) &p1->score, sizeof(float));
      p1 = p1->link; // 다음 노드
     }
    }


    int main(int argc, char* argv[])
    {
     StudentRecord S, R; // 임시 저장 레코드 S, R

     ifstream BinStudent(argv[1], ios::binary); // 파일열기
     ofstream Binout("output.bin", ios::binary);

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

     while (BinStudent.peek() != EOF) // 파일을 임시 레코드로 읽어
     {         // 임시레코드를 리스트에 추가
      S.readFromFile(BinStudent);
      S.addback();
     }

     bubble(ptr); // 리스트 정렬
     cout << "-----Sorted List(origin:student.bin)-----" << endl;
     cout << "[Num.]\t[Name]\t\t[Score]"<< endl;
     printList(ptr); // 리스트 화면 출력
     cout << "# Average Score : " << average(ptr) << endl; // 평균 화면 출력
     
     writeToFile(Binout, ptr); // 리스트 파일 출력

     Binout.close(); // output.bin 파일 ifstream으로 다시열기
     ifstream BinStudentSorted("output.bin", ios::binary);

     BinStudent.clear(); // 파일객체 리프래쉬
     BinStudent.seekg(0, ios::beg);
     BinStudentSorted.clear();
     BinStudentSorted.seekg(0, ios::beg);

     bool bc = true; // flag

     int findex = 0, sindex = 0; // 레코드 수를 저장할 변수
     while (BinStudent.peek() != EOF)
     {
      S.readFromFile(BinStudent);
      findex++; //첫번째 파일의 레코드수
     }
     while (BinStudentSorted.peek() != EOF)
     {
      R.readFromFile(BinStudentSorted);
      sindex++; //두번째 파일의 레코드수
     }

     //레코드 수검사
     cout << "\n파일 일치하는가?" << endl;
     if(findex != sindex)
     {
      cout << " 파일이 다릅니다.\n" << endl;

      BinStudent.clear(); // 파일객체 리프래쉬
      BinStudentSorted.clear();
      BinStudent.seekg(0, ios::beg);
      BinStudentSorted.seekg(0, ios::beg);

      cout << "student.bin " << endl; // 화면출력
      cout << "[Num.]\t[Name]\t\t[Score]"<< endl;
      while (BinStudent.peek() != EOF)
      {
       S.readFromFile(BinStudent);
       S.printRecord(cout);
      }

      cout << endl << "output.bin" << endl;
      cout << "[Num.]\t[Name]\t\t[Score]"<< endl;
      while (BinStudentSorted.peek() != EOF)
      {
       R.readFromFile(BinStudentSorted);
       R.printRecord(cout);
      }
      return 0;
     }


     // 레코드 내용이 같으지 검사
     while (BinStudent.peek() != EOF)
     {
      S.readFromFile(BinStudent);
      while(BinStudentSorted.peek() != EOF)
      {
       R.readFromFile(BinStudentSorted);
      if(S==R) // 두 레코드가 같은지 검사
       bc = true; // flag 에 true
      else
       bc = false; // flag 에 false
      }
     }

     //결과 출력
     if(bc==true) // flag가 true이면 같고 flase면 다르므로
     {    // 두파일의 일치여부와 내용을 화면출력
      cout << " \n\n  파일이 같습니다. \n\n" << endl;

      BinStudent.clear();
      BinStudentSorted.clear();
      BinStudent.seekg(0, ios::beg);
      BinStudentSorted.seekg(0, ios::beg);

      cout << "-----student.bin----- " << endl;
      cout << "[Num.]\t[Name]\t\t[Score]"<< endl;
      while (BinStudent.peek() != EOF)
      {
       S.readFromFile(BinStudent);
       S.printRecord(cout);
      }

      cout << endl << "-----output.bin-----" << endl;
      cout << "[Num.]\t[Name]\t\t[Score]"<< endl;
      while (BinStudentSorted.peek() != EOF)
      {
       R.readFromFile(BinStudentSorted);
       R.printRecord(cout);
      }
     }
     else
     {
      cout << " \n\n파일이 다릅니다.\n\n" << endl;

      BinStudent.clear();
      BinStudentSorted.clear();
      BinStudent.seekg(0, ios::beg);
      BinStudentSorted.seekg(0, ios::beg);

      cout << "-----student.bin-----" << endl;
      while (BinStudent.peek() != EOF)
      {
       S.readFromFile(BinStudent);
       S.printRecord(cout);
      }

      cout << endl << "-----output.bin-----" << endl;
      while (BinStudentSorted.peek() != EOF)
      {
       R.readFromFile(BinStudentSorted);
       R.printRecord(cout);
      }
      return 0;
     }

     BinStudent.close(); // 파일 닫기
     BinStudentSorted.close();

     return 0;
    }

Designed by Tistory.