// KeyList.cpp // CSI 2131 Asst 2b by Naim R. El-Far (naim@discover.uottawa.ca) // CSI 2131 - Winter 2006 - Prof. L.M. Moura // File: KeyList.cpp // Desc: Class KeyList definitions #include #include #include #include #include "KeyList.h" using namespace std; KeyList::KeyList() { keyListFileName = ""; keyListFileStream; numberOfKeysInList = 0; } KeyList::KeyList(string fileName) { keyListFileName = fileName; keyListFileStream.open(keyListFileName.c_str(), ios::out); keyListFileStream.close(); keyListFileStream.open(keyListFileName.c_str(), ios::in | ios::out | ios::binary); if (!keyListFileStream) { cerr << endl << "---------------------------------------------------" << endl << "Error! Specified key list file could not be opened!" << endl << "---------------------------------------------------" << endl << endl; exit(1); } else cout << "Key list file " << fileName << " opened successfully." << endl << endl; numberOfKeysInList = 0; } KeyList::~KeyList() { keyListFileStream.close(); } void KeyList::Insert(string studentNumber, long int listNext) { //Write student number in text mode keyListFileStream << studentNumber; //Write list next value in binary mode after converting from decimal to binary number keyListFileStream.write((char const*)(&listNext), 4); } void KeyList::WriteByRRN(long int RRN, string studentNumber, long int listNext) { long int entryOffset = keyListFileStream.tellg(); keyListFileStream.clear(); keyListFileStream.seekp(RRN * KEY_LIST_RECORD_SIZE); Insert(studentNumber, listNext); keyListFileStream.clear(); keyListFileStream.seekg(entryOffset); } void KeyList::UpdateListNext(long int givenRRN, long int newListNextValue) { string originalStudentNumber = ""; long int originalListNext = -2; ReadByRRN(givenRRN, originalStudentNumber, originalListNext); WriteByRRN(givenRRN, originalStudentNumber, newListNextValue); } void KeyList::ReadByRRN(long int RRN, string& studentNumber, long int& listNext) { //Given an RRN and a string and long int in which to store the read values, retrieve the student number and list next values and store them in the given variables long int entryOffset = keyListFileStream.tellg(); keyListFileStream.clear(); keyListFileStream.seekg(RRN * KEY_LIST_RECORD_SIZE); char studentNumberChar[20]; keyListFileStream.read(studentNumberChar, 7); keyListFileStream.read((char*)(&listNext), 4); studentNumber = ""; for (int i = 0 ; i < 7 ; i++) studentNumber = studentNumber + studentNumberChar[i]; keyListFileStream.clear(); keyListFileStream.seekg(entryOffset); } void KeyList::IncrementNumberOfKeys() { numberOfKeysInList++; } long int KeyList::InsertIntoInvertedList(long int listHead, string studentNumberToInsert) { //Called only if there are duplicate secondary keys (i.e. last names) bool done = false; long int lookingAtRRN = listHead; //Indicates the current RRN long int listNext = -2; //Indicates the next RRN long int listPrevious = -2; //Indicates the previous RRN long int newListHead = -2; int intGivenStudentNumber = atoi(studentNumberToInsert.c_str()); while (!done) { string retrievedStudentNumber = ""; ReadByRRN(lookingAtRRN, retrievedStudentNumber, listNext); int intRetrievedStudentNumber = atoi(retrievedStudentNumber.c_str()); if (intGivenStudentNumber == intRetrievedStudentNumber) { cerr << endl << "---------------------------------" << endl << "Error! Duplicate student numbers!" << endl << "---------------------------------" << endl << endl; exit(1); } else if (intGivenStudentNumber > intRetrievedStudentNumber) { if (listNext == -1) { newListHead = listHead; //List head doesn't change UpdateListNext(lookingAtRRN, numberOfKeysInList); WriteByRRN(numberOfKeysInList, studentNumberToInsert, -1); //Add to the end of the list done = true; } else { listPrevious = lookingAtRRN; lookingAtRRN = listNext; } } else { //if (intGivenStudentNumber < intRetrievedStudentNumber) WriteByRRN(numberOfKeysInList, studentNumberToInsert, lookingAtRRN); //We are appending to the list, so we're inserting at the last position + 1 if (lookingAtRRN == listHead) //If we're inserting at the beginning of a list, the list head changes newListHead = numberOfKeysInList; else { newListHead = listHead; //List head doesn't change UpdateListNext(listPrevious, numberOfKeysInList); //Update the previous record to point to this record } done = true; } } numberOfKeysInList++; return newListHead; } void KeyList::PrintList(ostream& str) { str << setw(7) << setiosflags(ios::left) << "Number" << '\t' << setw(10) << setiosflags(ios::left) << "List Next" << endl << setw(7) << setiosflags(ios::left) << "------" << '\t' << setw(10) << setiosflags(ios::left) << "---------" << endl; string studentNumber = ""; long int listNext = -2; for (int i = 0 ; i < numberOfKeysInList ; i++) { ReadByRRN(i, studentNumber, listNext); str << setw(7) << setiosflags(ios::left) << studentNumber << '\t' << setw(10) << setiosflags(ios::left) << listNext << endl; } str << "--END OF KEY LIST--" << endl; }