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