I keep running into an issue with a program for one of my classes. I'm definitely new to C++ and am hoping someone sees something obvious that I'm just missing. Every time I run it, it successfully compiles but then hits me with three EXC_BAD_ACCESS (code=EXC_I386_GPFLT) errors - one during my definition of the member function Employee::getID(), again in my search() function, and last when I call the search() function in main (all of which have the getID() function inside them. I'm wondering if this is part of a greater problem relating to use of pointers. Any advice would be greatly appreciated - thanks!
#include <iostream>
#include <iomanip>
#include <string>
#include <fstream>
using namespace std;
const int MAX_NUMBER_OF_EMPLOYEES {100}, // constant number of employees
DEPENDANT_INSURANCE {20}; // constant insurance cost per dependant;
const float TAX_RATE {0.15}; // constant tax rate
// declaration for Employee class
class Employee
{
private:
int id; // employee ID
char name[21]; // employee name
double hourlyPay; // pay per hour
int numDeps; // number of dependents
int type; // employee type
public:
Employee( int initId=0, char initName[]=0,
double initHourlyPay=0.0,
int initNumDeps=0, int initType=0 ); // Constructor
bool set(int newId, char newName[], double newHourlyPay,
int newNumDeps, int newType); // set function that performs input validation
int getID(); // gets employee ID
string getName(); // gets employee name
double getHourlyPay(); // gets employee hourly pay
int getNumDeps(); // gets employee's number of dependents
int getType(); // gets employee's type (union/management)
friend void setEmployees( ifstream&, Employee*[], int&);
};
// declaration for TimecardInfo struct that holds variables for employee
// hours worked, gross pay, tax, insurance, and net pay.
struct TimesheetInfo
{
float hoursWorked, // hours worked
grossPay, // gross pay
tax, // tax taken out
insurance, // insurance for dependents taken out
netPay; // net pay
int transID; // temporary ID to match getID() search
};
void setEmployees( ifstream&, Employee*[], int&);
void setTimesheet( ifstream&, TimesheetInfo*[], int&);
int search( int, Employee*[], int);
void bubbleSort (TimesheetInfo*[], int size);
// begin main function
int main()
{
float totalGrossPay {0.0}, // float variable for gross pay for all employees
totalNetPay {0.0}; // float variable for net pay for all employees
int totalTransactions {0}, // int to hold total number of correctly processed transactions
i = 0, // index for loop
searchIndex,
tempSearch,
numEmployees = 0,
numTrans = 0;
string inputFileName,
outputFileName;
// Employee *employee;
// TimesheetInfo *timesheet = nullptr;
Employee *employee [MAX_NUMBER_OF_EMPLOYEES]; // declare an array of pointers to Employee objects
TimesheetInfo *timesheet [MAX_NUMBER_OF_EMPLOYEES]; // declare an array of pointer to TimesheetInfo structures
ifstream inputFile; // create a filestream object
cout << "Enter the name of the employee master data file: ";
getline(cin, inputFileName);
//inputFile.open(inputFileName); // open file into inputFile
inputFile.open("/Users/davidfralin/Documents/Programming/ACCProgramming/ACC/Xcode Projects/Assignment10/Assignment10/master10.txt");
while (!inputFile)
{
cout << "Error opening file: please enter a valid file name: ";
getline(cin, inputFileName);
inputFile.open(inputFileName);
}
setEmployees(inputFile, employee, numEmployees);
// close input file
inputFile.close();
// create and open second input file
ifstream inputFile2;
cout << "Enter the name of the employee transaction data file: ";
getline(cin, inputFileName);
//inputFile2.open(inputFileName);
inputFile2.open("/Users/davidfralin/Documents/Programming/ACCProgramming/ACC/Xcode Projects/Assignment10/Assignment10/trans10.txt");
while (!inputFile2)
{
cout << "Error opening file: please enter a valid file name: ";
getline(cin, inputFileName);
inputFile2.open(inputFileName);
}
// create and open output file
ofstream outputFile;
cout << "Enter a name for the payroll report file: ";
getline(cin, outputFileName);
cout << outputFileName;
//outputFile.open(outputFileName);
outputFile.open("/Users/davidfralin/Documents/Programming/ACCProgramming/ACC/Xcode Projects/Assignment10/Assignment10/payroll_report_3.0.txt");
// Print formatted header for payroll report into output file
outputFile << fixed << showpoint << setprecision(2)
<< "****************************************************************\n"
<< "****************** ARMADILLO AUTOMOTIVE GROUP ******************\n"
<< "****************** PAYROLL REPORT 3.0 ******************\n"
<< "****************************************************************\n\n"
<< setw(3) << "ID" << " " << left
<< setw(20) << "Name" << right
<< setw(10) << "Gross Pay"
<< setw(10) << "Tax"
<< setw(10) << "Insurance"
<< setw(10) << "Net Pay" << endl
<< "****************************************************************" << endl;
// begin loop that iterates as many times as there are employees,
// which receives the employee's hours worked from inputFile2, perfoms
// needed calculations, and prints formatted results to output file
//inputFile2 >> timesheet[i].transID >> timesheet[i].hoursWorked;
setTimesheet(inputFile2, timesheet, numTrans);
bubbleSort(timesheet, numTrans);
cout << fixed << showpoint << setprecision(2) << endl
<< "****************************************************************\n"
<< "****************** ARMADILLO AUTOMOTIVE GROUP ******************\n"
<< "**************** ERROR & CONTROL REPORT ****************\n"
<< "****************************************************************\n\n";
for (i=0; i < numTrans; i++)
{
tempSearch = timesheet[i]->transID;
searchIndex = search(tempSearch, employee, numTrans);
if (searchIndex == -1)
{
cout << "Error: no matching employee data for Employee #:" << timesheet[i]->transID << endl << "\t*Employee info will not appear in payroll report*\n\n";
}
for (int j=0; j < numEmployees; j++)
{
if (timesheet[i]->transID == employee[j]->getID())
{
// input validation for employee ID - if invalid, print error message and do not store
// employee's info in output file.
if (!employee[j]->getID())
{
cout << "Error: invalid Employee ID for Employee Transaction: " << i+1 << endl
<< "\t*Employee info will not appear in payroll report*\n\n";
}
// input validation for employee's hours worked - if invalid, print error message and
// do not store employee's info in output file.
else if (timesheet[i]->hoursWorked < 0)
{
cout << "Error: invalid hours worked for Employee #:" << timesheet[i]->transID << endl
<< "\t*Employee info will not appear in payroll report*\n\n";
}
// with valid input verified, check for overtime and perfom needed calculations
else
{
// if employee is a union worker and worked overtime, calculate gross pay w/ overtime
// and store in struct relative to this iteration
if (timesheet[i]->hoursWorked > 40 && employee[j]->getType() == 0)
{
timesheet[i]->grossPay = (40 * employee[j]->getHourlyPay()) + (timesheet[i]->hoursWorked - 40) * employee[j]->getHourlyPay() * 1.5;
}
// if employee is management or union and didn't work overtime, calculate gross pay
// and store in struct relative to this iteration
else
{
timesheet[i]->grossPay = employee[j]->getHourlyPay() * timesheet[i]->hoursWorked;
}
// calculate and store tax, insurance, and net pay for this iteration
timesheet[i]->tax = timesheet[i]->grossPay * TAX_RATE;
timesheet[i]->insurance = employee[j]->getNumDeps() * DEPENDANT_INSURANCE;
timesheet[i]->netPay = timesheet[i]->grossPay - timesheet[i]->tax - timesheet[i]->insurance;
outputFile << right << setw(3) << employee[j]->getID() << " "
<< setw(20) << employee[j]->getName()
<< setw(10) << timesheet[i]->grossPay << setw(10) << timesheet[i]->tax << setw(10)
<< timesheet[i]->insurance << setw(10) << timesheet[i]->netPay << endl;
// add to running total correctly processed transactions, total gross pay, and total net pay
totalTransactions++;
totalGrossPay += timesheet[i]->grossPay;
totalNetPay += timesheet[i]->netPay;
}
}
}
}
// close input file
inputFile2.close();
// output to file formatted results for total gross/net pay
outputFile << endl << right << setw(24) << "Total Gross Pay: "
<< setw(10) << totalGrossPay << " "
<< setw(19) << "Total Net Pay: "
<< setw(10) << totalNetPay << endl
<< "****************************************************************" << endl;
// close output file
outputFile.close();
// output to file total number of transactions processed w/o error
cout << "Total transaction correctly processed: " << totalTransactions << endl << endl;
delete [] *employee;
delete [] *timesheet;
return 0;
}
//********************************************************
// Employee constructor *
// Employee class contructor that sets the object's data *
// members. If the input validation from function "set" *
// returns "false", initializes all name to a blank *
// string and all other values to 0. *
//********************************************************
Employee::Employee( int initId, char initName[],
double initHourlyPay,
int initNumDeps, int initType )
{
bool status = set( initId, initName, initHourlyPay,
initNumDeps, initType );
if ( !status )
{
id = 0;
strcpy(name, "");
hourlyPay = 0.0;
numDeps = 0;
type = 0;
}
}
//********************************************************
// Employee::set *
// Employee class member function that that performs *
// input validation on passed parameters, and if valid, *
// sets their values and returns "true."
//********************************************************
bool Employee::set( int newId, char newName[], double newHourlyPay,
int newNumDeps, int newType )
{
bool status = false;
if ( newId > 0 && newHourlyPay > 0 && newNumDeps >= 0 &&
newType >= 0 && newType <= 1 )
{
status = true;
id = newId;
strcpy(name, newName);
hourlyPay = newHourlyPay;
numDeps = newNumDeps;
type = newType;
}
return status;
}
//********************************************************
// Employee::getID *
// Employee class member function that returns the ID of *
// the class object. *
//********************************************************
int Employee::getID()
{
return id;
}
//********************************************************
// Employee::getName *
// Employee class member function that returns the name *
// of the class object. *
//********************************************************
string Employee::getName()
{
return name;
}
//********************************************************
// Employee::getHourlyPay *
// Employee class member function that returns the *
// hourly pay of the class object. *
//********************************************************
double Employee::getHourlyPay()
{
return hourlyPay;
}
//********************************************************
// Employee::getNumDeps *
// Employee class member function that returns the *
// number of dependents of the class object. *
//********************************************************
int Employee::getNumDeps()
{
return numDeps;
}
//********************************************************
// Employee::getType *
// Employee class member function that returns the type *
// of the class object (union or management). *
//********************************************************
int Employee::getType()
{
return type;
}
void bubbleSort (TimesheetInfo* array[], int size)
{
bool madeAswap = true; // This allows the for loop to begin iterating
for (int maxElement = (size - 1); maxElement > 0 && madeAswap; maxElement--)
{
for (int index = 0; index < maxElement; index++)
{
if (array[index]->transID > array[index + 1]->transID)
{
swap (array[index], array[index + 1]);
madeAswap = true;
}
}
}
}
//************************************************************** //* FUNCTION search
//*
//* Find the location of an item in a list.
//*
//**************************************************************
int search( int srchVal, // in - value to search for
Employee *list[], // in - list to search
int length) // in - number of items in list
{
// search list for item and return its position if found
int index = 0;
while (index < length)
{
if (srchVal == list[index]->getID())
return index;
index++;
}
// item not found - return a flag
return -1;
}
//**************************************************************
//* FUNCTION getItems
//*
//* Copies item information from file into arrays
//**************************************************************
void setEmployees( ifstream &employeeFile, Employee *employeePtr[], int &numEmployees)
{
int oneID; // employee ID
char oneName[21]; // employee name
double oneHourlyPay; // pay per hour
int oneNumDeps; // number of dependents
int oneType; // employee type
numEmployees = 0;
employeeFile >> oneID;
employeeFile.get( oneName, 21, '\n' );
employeeFile >> oneHourlyPay >> oneNumDeps >> oneType;
while (employeeFile && numEmployees < MAX_NUMBER_OF_EMPLOYEES)
{
// move new item into arrays and increment item count
employeePtr[numEmployees] = new Employee;
employeePtr[numEmployees]->id = oneID;
strcpy(employeePtr[numEmployees]->name, oneName);
employeePtr[numEmployees]->hourlyPay = oneHourlyPay;
employeePtr[numEmployees]->numDeps = oneNumDeps;
employeePtr[numEmployees]->type = oneType;
numEmployees++;
// get next item information
employeeFile >> oneID;
employeeFile.get( oneName, 21, '\n' );
employeeFile >> oneHourlyPay >> oneNumDeps >> oneType;
}
}
void setTimesheet( ifstream &transFile, TimesheetInfo *timesheetPtr[], int &numTrans)
{
int oneID; // temporary ID to match getID() search
float oneHoursWorked; // hours worked
numTrans = 0;
transFile >> oneID >> oneHoursWorked;
while (transFile && numTrans < MAX_NUMBER_OF_EMPLOYEES)
{
// move new item into arrays and increment item count
timesheetPtr[numTrans] = new TimesheetInfo;
timesheetPtr[numTrans]->transID = oneID;
timesheetPtr[numTrans]->hoursWorked = oneHoursWorked;
numTrans++;
// get next timesheet information
transFile >> oneID >> oneHoursWorked;
}
}