//********************************************************
//
// Assignment 7 - Structures and Strings
//
// Name: <Mario Morkus>
//
// Class: C Programming, <Spring 2026>
//
// Date: <03/29/2026>
//
// Description: Program which determines overtime and
// gross pay for a set of employees with outputs sent
// to standard output (the screen).
//
// This assignment also adds the employee name, their tax state,
// and calculates the state tax, federal tax, and net pay. It
// also calculates totals, averages, minimum, and maximum values.
//
// Call by Reference design
//
//********************************************************
// necessary header files
#include <stdio.h>
#include <string.h>
#include <ctype.h>
// define constants
#define SIZE 5 // number of employees
#define STD_HOURS 40.0 // standard hours before overtime kicks in
#define OT_RATE 1.5 // overtime pay multiplier
#define MA_TAX_RATE 0.05 // Massachusetts state tax rate
#define NH_TAX_RATE 0.0 // New Hampshire state tax rate (no income tax)
#define VT_TAX_RATE 0.06 // Vermont state tax rate
#define CA_TAX_RATE 0.07 // California state tax rate
#define DEFAULT_TAX_RATE 0.08 // default tax rate for any other state
#define NAME_SIZE 20 // max size for a full name string
#define TAX_STATE_SIZE 3 // max size for a 2-letter state + null terminator
#define FED_TAX_RATE 0.25 // federal tax rate applied to all employees
#define FIRST_NAME_SIZE 10 // max size for the first name string
#define LAST_NAME_SIZE 10 // max size for the last name string
// Define a structure type to store an employee name.
// Breaking the name into first and last gives flexibility for
// formatting and future extensions (middle name, prefix, etc.).
struct name
{
char firstName[FIRST_NAME_SIZE]; // employee's first name
char lastName [LAST_NAME_SIZE]; // employee's last name
};
// Define a structure type to pass employee data between functions.
// Note that the structure type is global, but variables of this type
// should be declared locally in functions and passed as needed.
struct employee
{
struct name empName; // employee's first and last name
char taxState[TAX_STATE_SIZE]; // 2-letter state abbreviation where work is performed
long int clockNumber; // unique employee clock/ID number
float wageRate; // hourly wage rate
float hours; // total hours worked in the week
float overtimeHrs; // overtime hours worked beyond STD_HOURS
float grossPay; // gross pay before taxes
float stateTax; // state tax owed based on tax state
float fedTax; // federal tax owed
float netPay; // take-home pay after all taxes
};
// This structure type defines the running totals of all floating point
// items so they can be summed and used to calculate averages.
struct totals
{
float total_wageRate; // sum of all employee wage rates
float total_hours; // sum of all hours worked
float total_overtimeHrs; // sum of all overtime hours
float total_grossPay; // sum of all gross pay values
float total_stateTax; // sum of all state taxes
float total_fedTax; // sum of all federal taxes
float total_netPay; // sum of all net pay values
};
// This structure type defines the minimum and maximum values of all
// floating point items so they can be displayed in the final report.
struct min_max
{
float min_wageRate; // minimum wage rate across all employees
float min_hours; // minimum hours worked
float min_overtimeHrs; // minimum overtime hours
float min_grossPay; // minimum gross pay
float min_stateTax; // minimum state tax
float min_fedTax; // minimum federal tax
float min_netPay; // minimum net pay
float max_wageRate; // maximum wage rate across all employees
float max_hours; // maximum hours worked
float max_overtimeHrs; // maximum overtime hours
float max_grossPay; // maximum gross pay
float max_stateTax; // maximum state tax
float max_fedTax; // maximum federal tax
float max_netPay; // maximum net pay
};
// Function prototypes - declared here so functions can be called
// before their full definitions appear below main
void getHours (struct employee employeeData[], int theSize);
void calcOvertimeHrs (struct employee employeeData[], int theSize);
void calcGrossPay (struct employee employeeData[], int theSize);
void printHeader (void);
void printEmp (struct employee employeeData[], int theSize);
void calcStateTax (struct employee employeeData[], int theSize);
void calcFedTax (struct employee employeeData[], int theSize);
void calcNetPay (struct employee employeeData[], int theSize);
struct totals calcEmployeeTotals (struct employee employeeData[],
struct totals employeeTotals,
int theSize);
struct min_max calcEmployeeMinMax (struct employee employeeData[],
struct min_max employeeMinMax,
int theSize);
void printEmpStatistics (struct totals employeeTotals,
struct min_max employeeMinMax,
int theSize);
int main ()
{
// Set up a local array of employee structures with pre-initialized
// name, tax state, clock number, and wage rate for each employee.
// Hours and calculated fields will be filled in later.
struct employee employeeData[SIZE] = {
{ {"Connie", "Cobol"}, "MA", 98401, 10.60 },
{ {"Mary", "Apl"}, "NH", 526488, 9.75 },
{ {"Frank", "Fortran"}, "VT", 765349, 10.50 },
{ {"Jeff", "Ada"}, "NY", 34645, 12.25 },
{ {"Anton", "Pascal"}, "CA", 127615, 8.35 }
};
// Structure to accumulate running totals of all float fields;
// initialized to zero so the running sums start clean.
struct totals employeeTotals = {0, 0, 0, 0, 0, 0, 0};
// Structure to hold minimum and maximum values of all float fields;
// initialized to zero and will be set to real values in calcEmployeeMinMax.
struct min_max employeeMinMax = {0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0};
// Prompt the user to enter hours worked for each employee
getHours (employeeData, SIZE);
// Calculate the overtime hours for each employee
calcOvertimeHrs (employeeData, SIZE);
// Calculate the weekly gross pay for each employee
calcGrossPay (employeeData, SIZE);
// Calculate the state tax owed for each employee
calcStateTax (employeeData, SIZE);
// Calculate the federal tax owed for each employee
calcFedTax (employeeData, SIZE);
// Calculate the net take-home pay for each employee
calcNetPay (employeeData, SIZE);
// Accumulate totals across all employees (Call by Value - returns updated struct)
employeeTotals = calcEmployeeTotals (employeeData, employeeTotals, SIZE);
// Determine minimum and maximum values across all employees (Call by Value)
employeeMinMax = calcEmployeeMinMax (employeeData, employeeMinMax, SIZE);
// Print the table column headers
printHeader();
// Print the details for each employee in a formatted table row
printEmp (employeeData, SIZE);
// Print the summary statistics: totals, averages, min, and max
printEmpStatistics (employeeTotals, employeeMinMax, SIZE);
return (0); // success
} // main
//**************************************************************
// Function: getHours
//
// Purpose: Prompts the user to enter the number of hours worked
// for each employee and stores the value in the
// employee array of structures.
//
// Parameters:
//
// employeeData - array of employee structures (passed by reference)
// theSize - the number of employees in the array
//
// Returns: void
//
//**************************************************************
void getHours (struct employee employeeData[], int theSize)
{
int i; // loop index used to iterate through each employee
// Loop through each employee and read in their hours worked
for (i = 0; i < theSize; ++i)
{
// Prompt using the employee's clock number for clarity
printf ("\nEnter hours worked by emp # %06li: ", employeeData
[i
].
clockNumber);
// Read the hours directly into the structure member (by reference via array)
scanf ("%f", &employeeData
[i
].
hours); }
} // getHours
//**************************************************************
// Function: printHeader
//
// Purpose: Prints the column header rows for the employee
// pay report table.
//
// Parameters: none
//
// Returns: void
//
//**************************************************************
void printHeader (void)
{
printf ("\n\n*** Pay Calculator ***\n");
// Print the top separator line
printf ("\n--------------------------------------------------------------"); printf ("-------------------");
// Print the two header rows with column labels
printf ("\nName Tax Clock# Wage Hours OT Gross ");
// Print the bottom separator line under the header
printf ("\n--------------------------------------------------------------"); printf ("-------------------");
} // printHeader
//*************************************************************
// Function: printEmp
//
// Purpose: Iterates through the employee array and prints all
// computed fields for each employee in a formatted
// table row.
//
// Parameters:
//
// employeeData - array of employee structures (passed by reference)
// theSize - the number of employees in the array
//
// Returns: void
//
//**************************************************************
void printEmp (struct employee employeeData[], int theSize)
{
int i; // loop index used to iterate through each employee
// Character array to hold the combined "First Last" full name.
// Size accounts for both name parts plus one space and the null terminator.
char name[FIRST_NAME_SIZE + LAST_NAME_SIZE + 1];
// Loop through each employee and print a formatted row
for (i = 0; i < theSize; ++i)
{
// Build the full names string by copying the first name,
// appending a space, then appending the last name.
// Using C string functions here demonstrates how to work with
// string data stored in separate structure members.
strcpy (name
, employeeData
[i
].
empName.
firstName); strcat (name
, " "); // insert a space between first and last name strcat (name
, employeeData
[i
].
empName.
lastName);
// Print all fields for this employee in one formatted line
printf ("\n%-20.20s %-2.2s %06li %5.2f %4.1f %4.1f %7.2f %6.2f %7.2f %8.2f", name,
employeeData[i].taxState,
employeeData[i].clockNumber,
employeeData[i].wageRate,
employeeData[i].hours,
employeeData[i].overtimeHrs,
employeeData[i].grossPay,
employeeData[i].stateTax,
employeeData[i].fedTax,
employeeData[i].netPay);
} // for
} // printEmp
//*************************************************************
// Function: printEmpStatistics
//
// Purpose: Prints the summary section of the report, including
// the totals, averages, minimums, and maximums for all
// floating point fields across all employees.
//
// Parameters:
//
// employeeTotals - structure holding the running sum of all
// employee floating point fields
// employeeMinMax - structure holding the minimum and maximum
// values for all employee floating point fields
// theSize - total number of employees processed; used
// to guard against divide-by-zero when averaging
//
// Returns: void
//
//**************************************************************
void printEmpStatistics (struct totals employeeTotals,
struct min_max employeeMinMax,
int theSize)
{
// Print the separator line before the statistics section
printf ("\n--------------------------------------------------------------"); printf ("-------------------");
// Print the totals row for every floating point column
printf ("\nTotals: %5.2f %5.1f %5.1f %7.2f %6.2f %7.2f %8.2f", employeeTotals.total_wageRate,
employeeTotals.total_hours,
employeeTotals.total_overtimeHrs,
employeeTotals.total_grossPay,
employeeTotals.total_stateTax,
employeeTotals.total_fedTax,
employeeTotals.total_netPay);
// Guard against dividing by zero or a negative count
if (theSize > 0)
{
// Print the averages row by dividing each total by the employee count
printf ("\nAverages: %5.2f %5.1f %5.1f %7.2f %6.2f %7.2f %8.2f", employeeTotals.total_wageRate / theSize,
employeeTotals.total_hours / theSize,
employeeTotals.total_overtimeHrs / theSize,
employeeTotals.total_grossPay / theSize,
employeeTotals.total_stateTax / theSize,
employeeTotals.total_fedTax / theSize,
employeeTotals.total_netPay / theSize);
} // if
// Print the minimum values row for every floating point column
printf ("\nMinimum: %5.2f %5.1f %5.1f %7.2f %6.2f %7.2f %8.2f", employeeMinMax.min_wageRate,
employeeMinMax.min_hours,
employeeMinMax.min_overtimeHrs,
employeeMinMax.min_grossPay,
employeeMinMax.min_stateTax,
employeeMinMax.min_fedTax,
employeeMinMax.min_netPay);
// Print the maximum values row for every floating point column
printf ("\nMaximum: %5.2f %5.1f %5.1f %7.2f %6.2f %7.2f %8.2f", employeeMinMax.max_wageRate,
employeeMinMax.max_hours,
employeeMinMax.max_overtimeHrs,
employeeMinMax.max_grossPay,
employeeMinMax.max_stateTax,
employeeMinMax.max_fedTax,
employeeMinMax.max_netPay);
} // printEmpStatistics
//*************************************************************
// Function: calcOvertimeHrs
//
// Purpose: Calculates the number of overtime hours worked by
// each employee. Any hours beyond STD_HOURS (40) are
// counted as overtime; otherwise overtime is zero.
//
// Parameters:
//
// employeeData - array of employee structures (passed by reference)
// theSize - the number of employees in the array
//
// Returns: void
//
//**************************************************************
void calcOvertimeHrs (struct employee employeeData[], int theSize)
{
int i; // loop index used to iterate through each employee
// Determine overtime hours for each employee
for (i = 0; i < theSize; ++i)
{
// If the employee worked more than standard hours, the excess is overtime
if (employeeData[i].hours >= STD_HOURS)
{
employeeData[i].overtimeHrs = employeeData[i].hours - STD_HOURS;
}
else
{
// No overtime hours earned this week
employeeData[i].overtimeHrs = 0;
}
} // for
} // calcOvertimeHrs
//*************************************************************
// Function: calcGrossPay
//
// Purpose: Calculates the gross pay for each employee by
// combining normal (straight-time) pay with any
// overtime pay earned during the week.
//
// Parameters:
//
// employeeData - array of employee structures (passed by reference)
// theSize - the number of employees in the array
//
// Returns: void
//
//**************************************************************
void calcGrossPay (struct employee employeeData[], int theSize)
{
int i; // loop index used to iterate through each employee
float theNormalPay; // pay earned for the standard (non-overtime) hours
float theOvertimePay; // additional pay earned for overtime hours at OT_RATE
// Calculate gross pay for each employee
for (i = 0; i < theSize; ++i)
{
// Normal pay covers all hours that are not overtime hours
theNormalPay = employeeData[i].wageRate *
(employeeData[i].hours - employeeData[i].overtimeHrs);
// Overtime pay is at 1.5x the regular wage rate
theOvertimePay = employeeData[i].overtimeHrs *
(OT_RATE * employeeData[i].wageRate);
// Gross pay is the sum of normal pay and any overtime pay
employeeData[i].grossPay = theNormalPay + theOvertimePay;
} // for
} // calcGrossPay
//*************************************************************
// Function: calcStateTax
//
// Purpose: Calculates the state income tax owed by each employee
// based on the state where they perform their work.
// Tax rates vary by state; any unrecognized state uses
// the default tax rate.
//
// Parameters:
//
// employeeData - array of employee structures (passed by reference)
// theSize - the number of employees in the array
//
// Returns: void
//
//**************************************************************
void calcStateTax (struct employee employeeData[], int theSize)
{
int i; // loop index used to iterate through each employee
// Determine and apply the appropriate state tax rate for each employee
for (i = 0; i < theSize; ++i)
{
// Normalize the tax state abbreviation to uppercase so that
// comparisons work correctly regardless of input case
if (islower (employeeData
[i
].
taxState[0])) employeeData
[i
].
taxState[0] = toupper (employeeData
[i
].
taxState[0]); if (islower (employeeData
[i
].
taxState[1])) employeeData
[i
].
taxState[1] = toupper (employeeData
[i
].
taxState[1]);
// Apply the correct state tax rate based on the employee's work state
if (strcmp (employeeData
[i
].
taxState, "MA") == 0) // Massachusetts: 5% state income tax
employeeData[i].stateTax = employeeData[i].grossPay * MA_TAX_RATE;
else if (strcmp (employeeData
[i
].
taxState, "NH") == 0) // New Hampshire: no state income tax (0%)
employeeData[i].stateTax = employeeData[i].grossPay * NH_TAX_RATE;
else if (strcmp (employeeData
[i
].
taxState, "VT") == 0) // Vermont: 6% state income tax
employeeData[i].stateTax = employeeData[i].grossPay * VT_TAX_RATE;
else if (strcmp (employeeData
[i
].
taxState, "CA") == 0) // California: 7% state income tax
employeeData[i].stateTax = employeeData[i].grossPay * CA_TAX_RATE;
else
// Any other state uses the default tax rate of 8%
employeeData[i].stateTax = employeeData[i].grossPay * DEFAULT_TAX_RATE;
} // for
} // calcStateTax
//*************************************************************
// Function: calcFedTax
//
// Purpose: Calculates the federal income tax owed by each
// employee. The same flat federal tax rate applies
// to all employees regardless of their state.
//
// Parameters:
//
// employeeData - array of employee structures (passed by reference)
// theSize - the number of employees in the array
//
// Returns: void
//
//**************************************************************
void calcFedTax (struct employee employeeData[], int theSize)
{
int i; // loop index used to iterate through each employee
// Apply the flat federal tax rate to each employee's gross pay
for (i = 0; i < theSize; ++i)
{
// Federal tax is a flat 25% of gross pay for all employees
employeeData[i].fedTax = employeeData[i].grossPay * FED_TAX_RATE;
} // for
} // calcFedTax
//*************************************************************
// Function: calcNetPay
//
// Purpose: Calculates the net (take-home) pay for each employee
// by subtracting both state and federal taxes from
// the employee's gross pay.
//
// Parameters:
//
// employeeData - array of employee structures (passed by reference)
// theSize - the number of employees in the array
//
// Returns: void
//
//**************************************************************
void calcNetPay (struct employee employeeData[], int theSize)
{
int i; // loop index used to iterate through each employee
float theTotalTaxes; // combined total of state and federal taxes owed
// Calculates the net (take-home) pay for each employee
for (i = 0; i < theSize; ++i)
{
// Combine state and federal taxes into a single tax amount
theTotalTaxes = employeeData[i].stateTax + employeeData[i].fedTax;
// Net pay is what the employee actually takes home after all taxes
employeeData[i].netPay = employeeData[i].grossPay - theTotalTaxes;
} // for
} // calcNetPay
//*************************************************************
// Function: calcEmployeeTotals
//
// Purpose: Accumulates a running sum of each floating point
// field across all employees in the array. The updated
// totals structure is returned to the caller.
//
// Parameters:
//
// employeeData - array of employee structures (passed by reference)
// employeeTotals - structure holding running totals (passed by value)
// theSize - the number of employees in the array
//
// Returns: employeeTotals - the updated totals structure
//
//**************************************************************
struct totals calcEmployeeTotals (struct employee employeeData[],
struct totals employeeTotals,
int theSize)
{
int i; // loop index used to iterate through each employee
// Add each employee's floating point values to the running totals
for (i = 0; i < theSize; ++i)
{
employeeTotals.total_wageRate += employeeData[i].wageRate;
employeeTotals.total_hours += employeeData[i].hours;
employeeTotals.total_overtimeHrs += employeeData[i].overtimeHrs;
employeeTotals.total_grossPay += employeeData[i].grossPay;
employeeTotals.total_stateTax += employeeData[i].stateTax;
employeeTotals.total_fedTax += employeeData[i].fedTax;
employeeTotals.total_netPay += employeeData[i].netPay;
} // for
// Returns the updated totals structure back to the calling function
return (employeeTotals);
} // calcEmployeeTotals
//*************************************************************
// Function: calcEmployeeMinMax
//
// Purpose: Determines the minimum and maximum values for each
// floating point field across all employees. The first
// employee's values seed both the min and max, and then
// each subsequent employee is compared to update them.
//
// Parameters:
//
// employeeData - array of employee structures (passed by reference)
// employeeMinMax - structure holding min/max values (passed by value)
// theSize - the number of employees in the array
//
// Returns: employeeMinMax - the updated min/max structure
//
//**************************************************************
struct min_max calcEmployeeMinMax (struct employee employeeData[],
struct min_max employeeMinMax,
int theSize)
{
int i; // loop index; starts at 1 since index 0 seeds the min and max
// Seed both min and max with the first employee's values
employeeMinMax.min_wageRate = employeeData[0].wageRate;
employeeMinMax.min_hours = employeeData[0].hours;
employeeMinMax.min_overtimeHrs = employeeData[0].overtimeHrs;
employeeMinMax.min_grossPay = employeeData[0].grossPay;
employeeMinMax.min_stateTax = employeeData[0].stateTax;
employeeMinMax.min_fedTax = employeeData[0].fedTax;
employeeMinMax.min_netPay = employeeData[0].netPay;
employeeMinMax.max_wageRate = employeeData[0].wageRate;
employeeMinMax.max_hours = employeeData[0].hours;
employeeMinMax.max_overtimeHrs = employeeData[0].overtimeHrs;
employeeMinMax.max_grossPay = employeeData[0].grossPay;
employeeMinMax.max_stateTax = employeeData[0].stateTax;
employeeMinMax.max_fedTax = employeeData[0].fedTax;
employeeMinMax.max_netPay = employeeData[0].netPay;
// Compare the remaining employees against the current min and max values
for (i = 1; i < theSize; ++i)
{
// --- Wage Rate ---
if (employeeData[i].wageRate < employeeMinMax.min_wageRate)
employeeMinMax.min_wageRate = employeeData[i].wageRate;
if (employeeData[i].wageRate > employeeMinMax.max_wageRate)
employeeMinMax.max_wageRate = employeeData[i].wageRate;
// --- Hours Worked ---
if (employeeData[i].hours < employeeMinMax.min_hours)
employeeMinMax.min_hours = employeeData[i].hours;
if (employeeData[i].hours > employeeMinMax.max_hours)
employeeMinMax.max_hours = employeeData[i].hours;
// --- Overtime Hours ---
if (employeeData[i].overtimeHrs < employeeMinMax.min_overtimeHrs)
employeeMinMax.min_overtimeHrs = employeeData[i].overtimeHrs;
if (employeeData[i].overtimeHrs > employeeMinMax.max_overtimeHrs)
employeeMinMax.max_overtimeHrs = employeeData[i].overtimeHrs;
// --- Gross Pay ---
if (employeeData[i].grossPay < employeeMinMax.min_grossPay)
employeeMinMax.min_grossPay = employeeData[i].grossPay;
if (employeeData[i].grossPay > employeeMinMax.max_grossPay)
employeeMinMax.max_grossPay = employeeData[i].grossPay;
// --- State Tax ---
if (employeeData[i].stateTax < employeeMinMax.min_stateTax)
employeeMinMax.min_stateTax = employeeData[i].stateTax;
if (employeeData[i].stateTax > employeeMinMax.max_stateTax)
employeeMinMax.max_stateTax = employeeData[i].stateTax;
// --- Federal Tax ---
if (employeeData[i].fedTax < employeeMinMax.min_fedTax)
employeeMinMax.min_fedTax = employeeData[i].fedTax;
if (employeeData[i].fedTax > employeeMinMax.max_fedTax)
employeeMinMax.max_fedTax = employeeData[i].fedTax;
// --- Net Pay ---
if (employeeData[i].netPay < employeeMinMax.min_netPay)
employeeMinMax.min_netPay = employeeData[i].netPay;
if (employeeData[i].netPay > employeeMinMax.max_netPay)
employeeMinMax.max_netPay = employeeData[i].netPay;
} // for
// Return the full updated min and max structure to the calling function
return (employeeMinMax);
} // calcEmployeeMinMax