/* Filename: modemp.cpp Author: Br. David Carlson Date: February 5, 1998 Revised: March 11, 2001 to avoid modifying employee names, as that could change a sorted array into unsorted, thus making binary search unsuitable. Last Revised: February 21, 2013 This program uses the emp.dat binary file of employee records, as created by the makeemp program. Specifically, this program lets the user repeatedly look up a given employee by name, displays the info on this employee, and then gives the user a chance to modify the ID and WageRate for this employee. Any modified data is written back to the same emp.dat file. It is assumed that the emp.dat file is already sorted by the employee names (last name, then first name, of course). If this is not the case, the lookup process is unlikely to work. Thus one needs to either enter the data in order into the makeemp program or one needs to use a program (like sortemp) that sorts the emp.dat file. Tested with: Microsoft Visual C++ 2008 g++ under Linux */ // iostream is indirectly included through employee.h #include // needed for files #include "employee.h" // needed for EmpType bool SearchFile(fstream & EmpFile, EmployeeType & Employee, long & Location); void Modify(EmployeeType & Employee, fstream & EmpFile, long Location); void ProcessFile(fstream & EmpFile); int main(void) { fstream EmpFile; EmpFile.open("emp.dat", ios::in | ios::out | ios::binary); if (EmpFile.fail()) { cerr << "Could not open file emp.dat" << endl; exit(1); } ProcessFile(EmpFile); EmpFile.close(); return 0; } /* Given: EmpFile A file stream already opened for input and output. Employee An employee record containing the last name and first name to search for. Assumes: That EmpFile is in ascending order. Task: To do a binary search in EmpFile for Employee. Return: EmpFile The file stream (which can be modified by reading and seeking in the file in that the file postion pointer may be moved). Employee If found, this parameter will contain the complete record for the person looked up. Location The location of the Employee record in the file (as the number of bytes into EmpFile). SearchFile In the function name, true is returned if Employee was located, false otherwise. */ bool SearchFile(fstream & EmpFile, EmployeeType & Employee, long & Location) { EmployeeType EmployeeTemp; bool Found; int CmpResult; long Mid, Low, High, RecordSize; Found = false; Low = 0L; // Go to the end of the file: EmpFile.seekg(0L, ios::end); RecordSize = sizeof(EmployeeTemp); // Find the number of records and subtract 1 to get high index: High = EmpFile.tellg() / RecordSize - 1L; while ((! Found) && (Low <= High)) { Mid = (Low + High) / 2; Location = Mid * RecordSize; EmpFile.seekg(Location, ios::beg); EmpFile.read(reinterpret_cast (&EmployeeTemp), RecordSize); CmpResult = EmpCompare(Employee, EmployeeTemp); if (CmpResult == 0) { Employee = EmployeeTemp; Found = true; } else if (CmpResult < 0) High = Mid - 1L; else Low = Mid + 1L; } return Found; } /* Given: Employee An employee record. EmpFile A file stream, open for input and output. Location The offset in EmpFile at which Employee can be found. Task: To allow the user to change the ID or WageRate in the Employee record, if desired, with the modified data being written to EmpFile. Return: Employee The (possibly) modified employee record. EmpFile The modified file stream for the file of records. */ void Modify(EmployeeType & Employee, fstream & EmpFile, long Location) { char Choice; bool Modified = false; cout << endl << "Do you wish to modify the ID number (y/n)? "; cin >> Choice; if ((Choice == 'y') || (Choice == 'Y')) { Modified = true; cout << "Enter the corrected ID number: "; cin >> Employee.ID; } cout << endl << "Do you wish to modify the wage rate (y/n)? "; cin >> Choice; if ((Choice == 'y') || (Choice == 'Y')) { Modified = true; cout << "Enter the corrected wage rate: "; cin >> Employee.WageRate; } if (Modified) { EmpFile.seekp(Location, ios::beg); EmpFile.write(reinterpret_cast (&Employee), sizeof(Employee)); } } /* Given: EmpFile A binary file stream already opened for input and output. Task: To allow the user to repeatedly look up an employee in EmpFile by name. If the lookup succeeds, the info on the employee is displayed on the screen and the user is given a chance to modify the ID and WageRate for the employee. Return: EmpFile The modified file stream. */ void ProcessFile(fstream & EmpFile) { EmployeeType Employee; long Location; // change to CTRL d for Linux cout << "Enter the last name of the employee to look up (CTRL z to quit)" << endl; cin >> Employee.LastName; while (! cin.fail()) { cout << "Enter the first name of the employee to look up" << endl; cin >> Employee.FirstName; if (SearchFile(EmpFile, Employee, Location)) { cout << endl; PrintEmployee(Employee); Modify(Employee, EmpFile, Location); } else cout << endl << "Not found" << endl; // change to CTRL d for Linux cout << endl << "Enter the last name of the employee to look up (CTRL z to quit)" << endl; cin >> Employee.LastName; } }