-
#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;
}