-
교수님의 친절한 개인지도 !! ^^*
#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;
}