// Title: A Simple Payroll Program -- Now with Structs // // Programmer: Bill McQuain // ID Number: 000-00-0000 // Compiler: Microsoft Visual C++ ver 4.0 // Platform: Pentium 120, Windows 95 // Date: December 2, 1996 // // Purpose: // // This program reads information about a group of employees from an // input file named "inpay.dat": // // - ID number // - age // - gross monthly salary // - insurance plan type // // and computes the correct deductions for: // // - federal income tax // - social security tax // - insurance fee // - net monthly salary. // // It then prints out a labeled table of results, showing for // each employee the ID number, gross salary, insurance fee, // income and social security tax deductions and net salary. // In addition, the averages of each category are computed and // printed. The list is sorted so net pay amounts are in increasing // order. // // The only modifications from ArrayPay.cpp are related to the use // of an array of struct variables to hold the employee records, // replacing the bouquet of parallel arrays used before. The // primary points of interest are the vastly simpler parameter lists // that are needed now, and the relatively trivial sorting code. // // The functions FedTax() and Insurance() required no modifications // at all -- since the parameters passed to them were individual // values, not arrays. // #include #include const int MaxEmp = 20; // maximum number of employees typedef struct { int IdNum; // employee's ID number int Age; // employee's age char InsPlan; // employee's insurance plan code float GrossPay; // employee's gross pay float InsFee; // employee's insurance fee float FIT; // employee's federal income tax float SSI; // employee's social security tax float NetPay; // employee's net pay } EmpRec; // Function prototypes. It's not necessary to include names for // the parameters here, but I recommend it because it helps keep // things straight. void ReadData(EmpRec Emp[], int& NumEmp); void CalcData(EmpRec Emp[], int NumEmp); float FedTax(float EmpGrossPay); float Insurance(char EmpInsPlan, int EmpAge); void SortData(EmpRec Emp[], int NumEmp); void PrintTable(const EmpRec Emp[],int NumEmp); void PrintHeader(ofstream& outPay); void CalcAvgs(ofstream& outPay, const EmpRec Emp[], int NumEmp); ////////////////////////////////////////////////////////////////////// // Beginning of main function: // int main() { // Local variables for main(): EmpRec Emp[MaxEmp]; // array of employee records int NumEmp; // number of employees // Read employee data from input file: ReadData(Emp, NumEmp); // Calculate employee withholding data and net pay: CalcData(Emp, NumEmp); // Sort the data so net pay amounts are in increasing order: SortData(Emp, NumEmp); // Print the table of employee information: PrintTable(Emp, NumEmp); return NumEmp; } ////////////////////////////////////////////////////////////////////// // The function ReadData reads employee data from the input file and // stores it in the array parameters. ReadData will read until the // end of the input file or until the arrays are filled (determined // by the global constant MaxEmp). // // Output parameters (passed by reference): // // Emp[] array of employee records // NumEmp number of employees for whom data was stored // // Remember: An array parameter is passed by reference by default, // so no ampersands (&) are needed for them. // // Also note: We don't need to specify the dimension of an array // parameter in the function definition (or in the // prototype). But you do need to indicate that it's an // array; that's the reason for the []s. // // ReadData must be able to handle the situation where there are more // lines of input data than will fit into the arrays. This is done // by using two mechanisms. First, the loop control for the while // includes both a check for a read failure and a check to be sure // that we're not about to try to store values past the end of the // arrays. Second, we read the input values into local variables // first, then transfer them to the arrays only if the array index is // valid (MaxEmp - 1 or less). // // One point that may be confusing. The local variable Index is used // to keep track of which array locations are to be stored into next. // When we exit the while loop, Index will point to the first unfilled // location in the arrays. However, Index will equal the number of // employees whose records were stored into the arrays. Remember that // in C++ we index arrays starting at 0 instead of 1. // void ReadData(EmpRec Emp[], int& NumEmp) { int Index = 0; // next array location to fill int empnum, // temp storage for employee id number empage; // employee age, float gross; // gross pay, and char plan; // insurance plan code ifstream inPay; // input file stream inPay.open("inpay.dat"); // open input file // Read first line of data from input file: inPay >> empnum >> empage >> gross >> plan; // Process and read next line until there's no more data or // we've filled up the arrays: while (inPay && Index < MaxEmp) { inPay.ignore(200, '\n'); // Skip to next line. Emp[Index].IdNum = empnum; // Store the last input line Emp[Index].Age = empage; // in an employee record Emp[Index].GrossPay = gross; Emp[Index].InsPlan = plan; inPay >> empnum >> empage >> gross >> plan; Index++; // Update index for next store } NumEmp = Index; // Remember: we never stored anything after // the last increment of Index inPay.close(); // Close the input file. } ///////////////////////////////////////////////////////////////////// // CalcData is used to calculate the net pay amounts for all // employees. // // Input Parameters (passed by value): // // NumEmp number of employees to be processed // // Input/Output Parameters (passed by reference): // // Emp[] array of employee records // void CalcData(EmpRec Emp[], int NumEmp){ const float SSRate = 0.0675f; // SSI tax rate ////////////////////////////////////////////////////////////// // Calculate the insurance fee, income tax, social security // tax and net pay for each employee, storing the results in // the relevant arrays: // for (int count = 0; count < NumEmp; count++) { Emp[count].InsFee = Insurance(Emp[count].InsPlan, Emp[count].Age); Emp[count].FIT = FedTax(Emp[count].GrossPay); Emp[count].SSI = SSRate * Emp[count].GrossPay; Emp[count].NetPay = Emp[count].GrossPay - Emp[count].FIT - Emp[count].SSI - Emp[count].InsFee; } } ///////////////////////////////////////////////////////////////////// // Insurance is used to calculate the proper insurance fee for an // employee. // // Input Parameters (passed by value): // // InsPlan character 'B' or 'D', indicating plan selected // Age employee's age // // Return value: // // InsFee insurance fee charged to employee // float Insurance(char InsPlan, int Age) { const float HiPlanB = 225.00f; // constants for insurance fees const float MidPlanB = 150.00f; const float LoPlanB = 100.00f; const float HiPlanD = 300.00f; const float MidPlanD = 200.00f; const float LoPlanD = 140.00f; const char PlanB = 'B'; // constants for plan types const char PlanD = 'D'; float InsFee= 0.0f; // insurance fee charged switch (InsPlan) { // Calculate insurance fee case 'B':{if (Age <= 35) // for Plan B InsFee = LoPlanB; else if (Age <= 65) InsFee = MidPlanB; else InsFee = HiPlanB; break; } case 'D':{if (Age <= 35) // for Plan D InsFee = LoPlanD; else if (Age <= 65) InsFee = MidPlanD; else InsFee = HiPlanD; break; } } return InsFee; } ///////////////////////////////////////////////////////////////////// // FedTax is used to calculate the proper income tax for an employee. // // Input Parameter (passed by value): // // GrossPay employee's gross pay amount // // Return value: // // FIT income tax withheld for employee // float FedTax(float GrossPay) { const float HiTax = 0.33f; // constants for tax rates const float MidTax = 0.28f; const float LoTax = 0.15f; const float HiIncome = 3000.00f; // constants for income levels const float MidIncome = 1000.00f; float FIT = 0.0f; // variable for income tax if (GrossPay >= HiIncome) { // Determine FIT amount. FIT = HiTax*GrossPay; } else if (GrossPay >= MidIncome) { FIT = MidTax*GrossPay; } else { FIT = LoTax*GrossPay; } return FIT; } ///////////////////////////////////////////////////////////////////// // SortData sorts the array of NetPay amounts into increasing order, // rearranging the data in the other arrays to keep everything // consistent. The selection sort algorithm is used. // // Input Parameters (passed by value): // // NumEmp number of employees // // Input/Output parameters (passed by reference): // // Emp[] array of employee records // // The function doesn't need to return a value, so it's void. // void SortData(EmpRec Emp[], int NumEmp) { int Begin, // beginning index for current pass Check, // index currently being checked SmallSoFar; // index of largest entry found so far EmpRec TmpEmp; // temporary storage used for swapping values // The outer loop runs us down the list NumEmp - 1 times: // for (Begin = 0; Begin < NumEmp - 1; Begin++) { SmallSoFar = Begin; // smallest so far is the first // The inner loop runs down the "tail" of the list, // determining where the smallest value is located. // // The value found will belong at the head of the "tail". // for (Check = Begin; Check < NumEmp; Check++) { if (Emp[Check].NetPay < Emp[SmallSoFar].NetPay) SmallSoFar = Check; } // Swap the employee record with smallest net pay amount, // located by the inner loop, to the right index: // TmpEmp = Emp[SmallSoFar]; Emp[SmallSoFar] = Emp[Begin]; Emp[Begin] = TmpEmp; } } ///////////////////////////////////////////////////////////////////// // PrintTable is used to print the table of employee data to output // file. // // Input Parameters (passed by value): // // Emp[] array of employee records // NumEmp number of employees to print data for // // The function doesn't need to return a value, so it's void. // void PrintTable(const EmpRec Emp[],int NumEmp) { ofstream outPay; // output file stream outPay.open("outpay.dat"); // open the output file // Set up for floating point output: outPay.setf(ios::fixed, ios::floatfield); outPay.setf(ios::showpoint); // Print the header for the table: // PrintHeader(outPay); // Print the table, line by line: // for (int count = 0; count < NumEmp; count++) { outPay << setw( 6) << Emp[count].IdNum; outPay << setw(12) << setprecision(2) << Emp[count].GrossPay; outPay << setw(10) << setprecision(2) << Emp[count].InsFee; outPay << setw(10) << setprecision(2) << Emp[count].FIT; outPay << setw(10) << setprecision(2) << Emp[count].SSI; outPay << setw(12) << setprecision(2) << Emp[count].NetPay; outPay << endl; } // Calculate and print averages: // CalcAvgs(outPay, Emp, NumEmp); } ///////////////////////////////////////////////////////////////////// // PrintHeader is used to print header for output file. // // Output Parameter (passed by reference): // // outPay output file stream variable // // The function does need to modify this stream (by inserting to // it), so the parameter must be passed by reference (with an // ampersand). // void PrintHeader(ofstream& outPay) { outPay << "Macro$oft Corporation March Payroll by Bill McQuain" << endl << endl; outPay << " IdNum" << " Gross Pay" << " Ins."; outPay << " F.I.T." << " SSI"; outPay << " Net Pay" << endl; outPay << "============================"; outPay << "================================" << endl; } ///////////////////////////////////////////////////////////////////// // CalcAvgs is used to print final averages to input file. // // Output Parameter (passed by reference): // // outPay output file stream variable // // Input Parameters (passed by value): // // Emp[] array of employee records // NumEmployees total number of employees // // The function doesn't need to return a value, so it's void. // void CalcAvgs(ofstream& outPay, const EmpRec Emp[], int NumEmp) { float TotalGross = 0.0f, // total of all gross pay TotalNet = 0.0f, // total of all net pay TotalIns = 0.0f, // total of all insurance fees TotalSSI = 0.0f, // total of all SS tax TotalFIT = 0.0f; // total of all income tax // Print out footer for table: outPay << "============================"; outPay << "================================" << endl; // If NumEmp > 0 then calculate totals and print out averages; // otherwise print zeros for the averages. // if (NumEmp) { for (int count = 0; count < NumEmp; count++) { TotalGross += Emp[count].GrossPay; TotalIns += Emp[count].InsFee; TotalFIT += Emp[count].FIT; TotalSSI += Emp[count].SSI; TotalNet += Emp[count].NetPay; } outPay << " Avg:"; outPay << setw(12) << setprecision(2) << TotalGross/NumEmp; outPay << setw(10) << setprecision(2) << TotalIns/NumEmp; outPay << setw(10) << setprecision(2) << TotalFIT/NumEmp; outPay << setw(10) << setprecision(2) << TotalSSI/NumEmp; outPay << setw(12) << setprecision(2) << TotalNet/NumEmp; outPay << endl; } else { outPay << " Avg:"; outPay << setw(12) << setprecision(2) << 0.0f; outPay << setw(10) << setprecision(2) << 0.0f; outPay << setw(10) << setprecision(2) << 0.0f; outPay << setw(10) << setprecision(2) << 0.0f; outPay << setw(12) << setprecision(2) << 0.0f; outPay << endl; } }