Author: Jeff Zhuk
Date: 07/03/95
Module: payroll.cpp
Description: This module is the main program for the PAYROLL project. It presents EMPLOYEE - related menu and prompts the user for a proper selection: 1. Load the payroll database file. 2. Add an employee to the database. 3. Remove an employee from the database. 4. Save the employee database into a file. 5. Display all the employee data. 6. Exit. There are several types of EMPLOYEE that get paid differently: Manager - gets its salary any way Hourly - paid by worked hours Sales - paid by hours plus percent of total sale Different employee types have slightly different data attributes. Each attribute for simplicity takes one line of characters. The first attribute in an employee record reflects an employee type. The employee database file is a text file, that can be displayed and printed by any editor. All the Employees are connected with a Linked List It means that each Employee (no matter what type) has a pointer to the NEXT Employee. ********************************************************/ #include < iostream.h> #include < conio.h> #include < stdio.h> #include < string.h> #include < ctype.h> #include "employee.h" #include "hourly.h" #include "sales.h" #include "manager.h" Employee *head=NULL; // Head pointer to the Linked List. // It must be unique, static and accessible throughout the program // 5 modules implementing 5 Use cases int LoadDatabase(); // returns number of employees loaded void AddEmployee(); // adds an Employee to the list of employees void RemoveEmployee(); void DisplayEmployees(); int SaveDatabase(); // returns number of employees saved // A Module used by all scenarios to create a new employee Employee* NewEmployee(char* employeeType); // Instantiates Employee of // a proper type and returns a pointer int main() // argc and argv can be used to provide database file name { int done = 0; // to indicate the user selected EXIT int counter; char buf[80]=""; // input string buffer while(!done) { // Display the PAYROLL database actions menu cout << "\nWelcome to the PAYROLL application" << endl; cout << " 1. Load payroll.txt database file.\n"; cout << " 2. Add an employee to the database.\n"; cout << " 3. Remove an employee from the database.\n"; cout << " 4. Display all the employees loaded.\n"; cout << " 5. Save the database into payroll.txt file.\n"; cout << " 6. Exit.\n"; // Prompt for desired action cout << "\nEnter the number of the desired action: "; // Get the number of the desired action // It expects any characters (but not just BLANK) and ENTER cin >> buf; // Integer can be used here, but a user (smart one) // can enter non-digit character to puzzle "cin" cin.ignore(1); // Determine the desired action and invoke the function switch (buf[0]) // The first character is analysed { // to recognize the user selection case '1': counter = LoadDatabase(); cout << "\nLoaded records=" << counter; break; case '2': AddEmployee(); break; case '3': RemoveEmployee(); break; case '4': DisplayEmployees(); break; case '5': counter = SaveDatabase(); cout << "\nWritten records=" << counter; break; case '6': done = 1; // EXIT break; default: cout << "\nInvalid action. Please re-enter\n" ; } } // Keep prompting until EXIT return done; } /********************************* int LoadDatabase() ******************** The function reads database file if Employee Linked List is empty (head==NULL). File can include all the Employee type records. Employee Type attribute and Employee* NewEmployee() function are used to recognize and make an instance of a proper employee type object. Then newEmp->Read() - polymorphic statement is used to read a proper record structure. **************************************************************************/ // int LoadDatabase() { FILE *fp; Employee *newEmp; Employee *previousEmp=NULL; char empType[80]=""; int counter=0; if(head) { // head pointer is not NULL, something is already loaded cout << "\nDatabase already loaded/created" ; return 0; } if((fp = fopen("payrol.txt", "r")) == NULL) { // can not open cout << "\nError opening file: payrol.txt \n"; return 0; } // read the file for(counter=0;fgets(empType,80,fp);counter++) { // read empType if(feof(fp)) // check for End Of File break; newEmp = NewEmployee(empType); // Employee of proper type if (newEmp==NULL) { // wrong type fclose(fp); // Error, stop reading return counter; // return from here } newEmp->Read(fp); // read the rest of the record // using proper Read() polymorphically // make a Linked List if(head==NULL) // set head pointer for a Linked List head = newEmp; else previousEmp->SetNext(newEmp); // set Next pointer previousEmp = newEmp; // for a previous Employee } // using Employee::SetNext fclose(fp); return counter; } Employee* NewEmployee(char* empType) // Instantiates Employee of proper type { // and returns a pointer to it Employee* newEmp=NULL; switch(empType[0]) // what type of employee is this { // Constructor works here case 'M': newEmp = new Manager; // Manager::Manager() break; case 'H': newEmp = new Hourly; // Hourly::Hourly() break; case 'S': newEmp = new Sales; // Sales::Sales() break; default: cout << "\nUnknown type of Employee=" << empType; } return newEmp; // the pointer will be NULL for unknown Employee type } void AddEmployee() // Prompts for the Employee data, Instantiates a proper { // type of Employee and adds it to the Linked List char empType[80]=""; Employee *newEmp=NULL; Employee *emp=NULL; // Prompt for desired employee type cout << "\nEnter type of Employee to add: M/H/S\n" ; cout << "M - for Manager; H - for Hourly or S - for Sales\n"; cin >> empType; newEmp=NewEmployee(empType); // instantiate Employee of proper type if (newEmp != NULL) // do nothing if no Employee instantiated or newEmp->Add(); // Add proper Employee polymorphically // by prompting a user for all the data // attach to a Linked List if(head==NULL) // set head pointer for a Linked List head = newEmp; else { //Find the last Employee on the list for(emp = head; emp->GetNext() != NULL; emp = emp->GetNext()); emp->SetNext(newEmp); // set Next pointer to the new Employee } // SetNext() and etNext() methods are defined in Employee (base) class } void RemoveEmployee() // Prompts a user for SSN, then finds and { // removes the Employee. Preserves Linked List integrity. Employee *emp=NULL; // current Employee on the List Employee *previousEmp=NULL; // previous Employee on the List char ssn[10]; cout << "\nEnter social security number of the employee: "; cin >> ssn; for(emp = head; emp != NULL; emp = emp->GetNext() ) { // search through if( strcmp(ssn,emp->GetSSN()) == 0) { // the Linked List for SSN // when found, first switch the pointers // to preserve Linked List integrity if (emp == head) // if it is first in the Linked List head = emp->GetNext(); // shift head pointer if(previousEmp != NULL) previousEmp->SetNext(emp->GetNext()); delete emp; // delete the object now break; } previousEmp = emp; // store the pointer for the next cycle } // when it will serve as previous one if( emp == NULL ) cout << "\nCan not find Employee with SSN=" << ssn; } int SaveDatabase() // search through the Linked List and { // saves each Employee of a proper type polymorphically FILE *fp; Employee *emp; int counter=0; if( head == NULL) { cout << "\nThere is nothing to save. \n"; return 0; } // open the file if ((fp = fopen("payrol.txt", "w")) == NULL) { // some problem cout << "\nCan not open payrol.txt file for writing"; return 0; } // save the file for(emp = head; emp != NULL; emp = emp->GetNext() ) { // search through emp->Save(fp); // Linked List and counter++; // save each Employee polymorphically } fclose(fp); // done, close the file return counter; } void DisplayEmployees() // Get all the Employees from the Linked List { // and display each type of Employee polymorphically Employee *emp; for(emp = head; emp != NULL; emp = emp->GetNext() ) { // search through emp->Display(); // Linked List and // display each Employee polymorphically cout << " Enter key to continue ..."; cin.get(); } } void DeleteEOL( char *str ) { str[ strlen( str ) -1 ] = '\0'; } ////////////////////////// employee.cpp //////////////////////// #include < iostream.h> #include < stdio.h> #include < string.h> #include "employee.h" void Employee::Read(FILE *fp) { fgets (Ssn,80,fp); DeleteEOL( Ssn ); fgets (Name,80,fp); DeleteEOL( Name ); fgets (BirthDate,80,fp); DeleteEOL( BirthDate ); fgets (HireDate,80,fp); DeleteEOL( HireDate ); } void Employee::Save(FILE *fp) { fprintf(fp, "%s\n", empType ); fprintf(fp, "%s\n", Ssn ); fprintf (fp, "%s\n", Name); fprintf (fp, "%s\n", BirthDate); fprintf (fp, "%s\n", HireDate); } void Employee::SetNext(Employee *newEmp) { this->next = newEmp; } Employee* Employee::GetNext() { return this->next ; } void Employee::Add( void ) { cout << " Enter Ssn :"; cin >> Ssn; // cout << endl; cout << " Enter Name :"; cin >> Name; cout << " Birth date :"; cin >> BirthDate; cout << " Hire date :"; cin >> HireDate; } void Employee::Display( void ) { cout << " E m p l o y e e : " << empType < /////////////////////////////// employee.h ///////////////////////////// #ifndef _EMPLOYEE_H_ #define _EMPLOYEE_H_ class Employee { protected: char empType[80]; char Ssn[80]; char Name[80]; char BirthDate[80]; char HireDate[80]; Employee *next; public: // functions Employee() { next = NULL;} virtual void Read(FILE *pf); virtual void Add(); virtual void Save(FILE *pf); virtual void Display(); char *GetSSN(){ return Ssn;}; Employee *GetNext(); void SetNext(Employee *); }; void DeleteEOL(char *); #endif //////////////////////// hourly.cpp ///////////////////////////// #include < iostream.h> #include < stdio.h> #include < string.h> #include "hourly.h" void Hourly::Read(FILE *fp) { Employee::Read( fp ); fgets (HourlyRate,80,fp); DeleteEOL( HourlyRate ); fgets (WorkHours,80,fp); DeleteEOL( WorkHours ); } void Hourly::Save(FILE *fp) { Employee::Save( fp ); fprintf (fp, "%s\n", HourlyRate ); fprintf (fp,"%s\n", WorkHours ); } void Hourly::Add( void ) { Employee::Add(); cout << " Enter Hourly rate :"; cin >> HourlyRate; cout << " Enter work hours :" ; cin >> WorkHours ; } void Hourly::Display( void ) { Employee::Display(); cout << " HourlyRate : " << HourlyRate << endl; cout << " Work hours : " << WorkHours << endl; }////////////////////////////////////// hourly.h ////////////////// #ifndef _HOURLY_H_ #define _HOURLY_H_ #include "employee.h" class Hourly : public Employee { // Hourly worker paid by worked hours char HourlyRate[80]; char WorkHours[80] ; public: Hourly():Employee(){ strcpy( empType, "H" );}; virtual void Read(FILE *pf); virtual void Add(); virtual void Save(FILE *pf); virtual void Display(); }; #endif /////////////////////////////// manager.cpp ////////////////////////// #include < iostream.h> #include < stdio.h> #include < string.h> #include "manager.h" void Manager::Read(FILE *fp)// : ( FILE *fp ) { Employee::Read( fp ); fgets (Salary,80,fp); DeleteEOL( Salary ); } void Manager::Save(FILE *fp)// : ( FILE *fp ) { Employee::Save( fp ); fprintf (fp, "%s\n", Salary); } void Manager::Add( void ) { Employee::Add(); cout << " Enter Salary :"; cin >> Salary; } void Manager::Display( void ) { Employee::Display(); cout << " Salary : " << Salary << endl; }/////////////////////////////////////// manager.h /////////////////////// #ifndef _MANAGER_H_ #define _MANAGER_H_ #include "employee.h" class Manager : public Employee { // Manager gets his salary any way char Salary[80] ; public: Manager() : Employee(){ strcpy( empType, "M" );}; virtual void Read(FILE *pf); virtual void Add(); virtual void Save(FILE *pf); virtual void Display(); }; #endif ///////////////////////// sales.cpp //////////////////////// #include < iostream.h> #include < stdio.h> #include < string.h> #include "sales.h" void Sales::Read(FILE *fp) { Hourly::Read( fp) ; fgets (TotalSale,80,fp); DeleteEOL( TotalSale ); fgets (PercentPaid,80,fp); DeleteEOL( PercentPaid ); } void Sales::Save(FILE *fp) { Hourly::Save( fp) ; fprintf( fp, "%s\n", TotalSale ); fprintf( fp, "%s\n", PercentPaid); } void Sales::Add( void ) { Hourly::Add(); cout << " Enter total sale :"; cin >> TotalSale; cout << " Enter percent paid:" ; cin >> PercentPaid ; } void Sales::Display( void ) { Hourly::Display(); cout << " Total sale :" << TotalSale << endl; cout << " Percent paid :" << PercentPaid << endl; }//////////////////////////// sales.h /////////////////////////// #ifndef _SALES_H_ #define _SALES_H_ #include "horly.h" class Sales : public Hourly { //Saler persen paid by worked hours + percent total sale char TotalSale[80]; char PercentPaid[80]; public: Sales() : Hourly(){ strcpy( empType, "S" ); }; virtual void Read(FILE *pf); // read proper record structure virtual void Add(); virtual void Save(FILE *pf); virtual void Display(); }; #endif