//********************************************************
//
// Assignment 9 - Employee Pay Calculator with Linked Lists
//
// Name: Felix Henriquez
//
// Class: C Programming, Fall 2025
//
// Date: November 16, 2025
//
// Description: Employee pay calculator using dynamically allocated linked lists
// with corrected state and federal tax calculations.
// Modified for ideone.com with batch input.
//
//********************************************************
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Constants for array sizes and business rules
#define FIRST_NAME_SIZE 21 // 20 characters + null terminator
#define LAST_NAME_SIZE 31 // 30 characters + null terminator
#define TAX_STATE_SIZE 3 // 2 characters + null terminator
#define STANDARD_WORK_WEEK 40.0
#define OVERTIME_RATE 1.5
#define FED_TAX_RATE 0.25
// Structure for employee data
struct employee
{
char firstName[FIRST_NAME_SIZE];
char lastName[LAST_NAME_SIZE];
char taxState[TAX_STATE_SIZE];
long int clockNumber;
float wageRate;
float hours;
float overtimeHrs;
float grossPay;
float stateTax;
float fedTax;
float netPay;
struct employee *next;
};
// Structure for summary statistics
struct totals
{
float totalWage;
float totalHours;
float totalOvertimeHrs;
float totalGrossPay;
float totalStateTax;
float totalFedTax;
float totalNetPay;
};
// Structure for min and max values
struct min_max
{
float minWage;
float minHours;
float minOvertimeHrs;
float minGrossPay;
float minStateTax;
float minFedTax;
float minNetPay;
float maxWage;
float maxHours;
float maxOvertimeHrs;
float maxGrossPay;
float maxStateTax;
float maxFedTax;
float maxNetPay;
};
// Function prototypes
void addEmployee(struct employee **head, int employeeNumber);
void deleteList(struct employee **head);
void calcOvertime(struct employee *head);
void calcGrossPay(struct employee *head);
float calcStateTax(float gross, char *state);
float calcFedTax(float gross);
void calcNetPay(struct employee *head);
void calcEmployeeTotals(struct employee *head, struct totals *empTotals);
void calcEmployeeMinMax(struct employee *head, struct min_max *empMinMax);
void printHeader(void);
void printEmployee(struct employee *emp);
void printSummary(struct totals *empTotals, struct min_max *empMinMax, int count);
/*****************************************************************************
* Function: main
*
* Purpose: Program entry point - manages employee data using linked lists
*
* Parameters: none
*
* Returns: int - program exit status
*****************************************************************************/
int main()
{
struct employee *head = NULL; // head of linked list
struct totals employeeTotals; // structure for totals
struct min_max employeeMinMax; // structure for min/max values
int employeeCount = 5; // we know we have exactly 5 employees
// Add all 5 employees from batch input
int i;
for(i = 0; i < 5; i++) {
addEmployee(&head, i+1);
}
// Calculate payroll values
calcOvertime(head);
calcGrossPay(head);
calcNetPay(head);
// Calculate summary statistics
calcEmployeeTotals(head, &employeeTotals);
calcEmployeeMinMax(head, &employeeMinMax);
// Display report
printHeader();
struct employee *current = head;
while (current != NULL) {
printEmployee(current);
current = current->next;
}
printSummary(&employeeTotals, &employeeMinMax, employeeCount);
// Clean up memory
deleteList(&head);
return 0;
}
/*****************************************************************************
* Function: addEmployee
*
* Purpose: Adds a new employee to the linked list from batch input
*
* Parameters: head - pointer to head of linked list
* employeeNumber - which employee we're adding (for debugging)
*
* Returns: void
*****************************************************************************/
void addEmployee(struct employee **head, int employeeNumber)
{
struct employee
*newEmployee
= (struct employee
*)malloc(sizeof(struct employee
)); struct employee *current;
if (newEmployee == NULL) {
printf("Memory allocation failed!\n"); }
// Read employee data from separate lines (ideone format)
// Each field is on its own line as specified in the assignment
if (scanf("%20s", newEmployee
->firstName
) != 1) { printf("Error reading first name for employee %d\n", employeeNumber
); }
if (scanf("%30s", newEmployee
->lastName
) != 1) { printf("Error reading last name for employee %d\n", employeeNumber
); }
if (scanf("%2s", newEmployee
->taxState
) != 1) { printf("Error reading tax state for employee %d\n", employeeNumber
); }
if (scanf("%ld", &newEmployee
->clockNumber
) != 1) { printf("Error reading clock number for employee %d\n", employeeNumber
); }
if (scanf("%f", &newEmployee
->wageRate
) != 1) { printf("Error reading wage rate for employee %d\n", employeeNumber
); }
if (scanf("%f", &newEmployee
->hours
) != 1) { printf("Error reading hours for employee %d\n", employeeNumber
); }
// Read the Y/N character but don't use it (we know we have exactly 5 employees)
char choice;
if (scanf(" %c", &choice
) != 1) { // If we can't read a character on the last one, that's OK
}
// Initialize calculated fields
newEmployee->overtimeHrs = 0.0;
newEmployee->grossPay = 0.0;
newEmployee->stateTax = 0.0;
newEmployee->fedTax = 0.0;
newEmployee->netPay = 0.0;
newEmployee->next = NULL;
// Add to linked list
if (*head == NULL) {
*head = newEmployee;
} else {
current = *head;
while (current->next != NULL) {
current = current->next;
}
current->next = newEmployee;
}
}
/*****************************************************************************
* Function: deleteList
*
* Purpose: Deletes all employees from the linked list and frees memory
*
* Parameters: head - pointer to head of linked list
*
* Returns: void
*****************************************************************************/
void deleteList(struct employee **head)
{
struct employee *current = *head;
struct employee *next;
while (current != NULL) {
next = current->next;
current = next;
}
*head = NULL;
}
/*****************************************************************************
* Function: calcOvertime
*
* Purpose: Calculates overtime hours for each employee
*
* Parameters: head - pointer to head of linked list
*
* Returns: void
*****************************************************************************/
void calcOvertime(struct employee *head)
{
struct employee *current = head;
while (current != NULL) {
if (current->hours > STANDARD_WORK_WEEK) {
current->overtimeHrs = current->hours - STANDARD_WORK_WEEK;
} else {
current->overtimeHrs = 0.0;
}
current = current->next;
}
}
/*****************************************************************************
* Function: calcGrossPay
*
* Purpose: Calculates gross pay including overtime at time-and-a-half
*
* Parameters: head - pointer to head of linked list
*
* Returns: void
*****************************************************************************/
void calcGrossPay(struct employee *head)
{
struct employee *current = head;
float regularHours;
float basePay;
float overtimePay;
while (current != NULL) {
regularHours = current->hours;
if (regularHours > STANDARD_WORK_WEEK) {
regularHours = STANDARD_WORK_WEEK;
}
basePay = regularHours * current->wageRate;
overtimePay = current->overtimeHrs * current->wageRate * OVERTIME_RATE;
current->grossPay = basePay + overtimePay;
current = current->next;
}
}
/*****************************************************************************
* Function: calcStateTax
*
* Purpose: Calculates state tax based on gross pay and state code
*
* Parameters: gross - gross pay amount
* state - state code string
*
* Returns: float - state tax amount
*****************************************************************************/
float calcStateTax(float gross, char *state)
{
if (strcmp(state
, "MA") == 0) return gross
* 0.05; // Massachusetts: 5% if (strcmp(state
, "NH") == 0) return 0.00; // New Hampshire: 0% if (strcmp(state
, "VT") == 0) return gross
* 0.06; // Vermont: 6% if (strcmp(state
, "CA") == 0) return gross
* 0.07; // California: 7% return gross * 0.08; // All other states: 8%
}
/*****************************************************************************
* Function: calcFedTax
*
* Purpose: Calculates federal tax based on gross pay
*
* Parameters: gross - gross pay amount
*
* Returns: float - federal tax amount
*****************************************************************************/
float calcFedTax(float gross)
{
return gross * FED_TAX_RATE; // Federal tax rate of 25%
}
/*****************************************************************************
* Function: calcNetPay
*
* Purpose: Calculates net pay for each employee
*
* Parameters: head - pointer to head of linked list
*
* Returns: void
*****************************************************************************/
void calcNetPay(struct employee *head)
{
struct employee *current = head;
while (current != NULL) {
// Calculate taxes using the tax functions
current->stateTax = calcStateTax(current->grossPay, current->taxState);
current->fedTax = calcFedTax(current->grossPay);
// Calculate net pay
current->netPay = current->grossPay - current->stateTax - current->fedTax;
current = current->next;
}
}
/*****************************************************************************
* Function: calcEmployeeTotals
*
* Purpose: Calculates total values for all employees
*
* Parameters: head - pointer to head of linked list
* empTotals - pointer to totals structure to store results
*
* Returns: void
*****************************************************************************/
void calcEmployeeTotals(struct employee *head, struct totals *empTotals)
{
struct employee *current = head;
// Initialize totals to zero
empTotals->totalWage = 0;
empTotals->totalHours = 0;
empTotals->totalOvertimeHrs = 0;
empTotals->totalGrossPay = 0;
empTotals->totalStateTax = 0;
empTotals->totalFedTax = 0;
empTotals->totalNetPay = 0;
// Calculate totals
while (current != NULL) {
empTotals->totalWage += current->wageRate;
empTotals->totalHours += current->hours;
empTotals->totalOvertimeHrs += current->overtimeHrs;
empTotals->totalGrossPay += current->grossPay;
empTotals->totalStateTax += current->stateTax;
empTotals->totalFedTax += current->fedTax;
empTotals->totalNetPay += current->netPay;
current = current->next;
}
}
/*****************************************************************************
* Function: calcEmployeeMinMax
*
* Purpose: Calculates minimum and maximum values for all employees
*
* Parameters: head - pointer to head of linked list
* empMinMax - pointer to min_max structure to store results
*
* Returns: void
*****************************************************************************/
void calcEmployeeMinMax(struct employee *head, struct min_max *empMinMax)
{
struct employee *current = head;
if (current == NULL) {
return; // No employees
}
// Initialize with first employee's values
empMinMax->minWage = current->wageRate;
empMinMax->minHours = current->hours;
empMinMax->minOvertimeHrs = current->overtimeHrs;
empMinMax->minGrossPay = current->grossPay;
empMinMax->minStateTax = current->stateTax;
empMinMax->minFedTax = current->fedTax;
empMinMax->minNetPay = current->netPay;
empMinMax->maxWage = current->wageRate;
empMinMax->maxHours = current->hours;
empMinMax->maxOvertimeHrs = current->overtimeHrs;
empMinMax->maxGrossPay = current->grossPay;
empMinMax->maxStateTax = current->stateTax;
empMinMax->maxFedTax = current->fedTax;
empMinMax->maxNetPay = current->netPay;
// Process remaining employees
current = current->next;
while (current != NULL) {
// Update minimum values
if (current->wageRate < empMinMax->minWage) empMinMax->minWage = current->wageRate;
if (current->hours < empMinMax->minHours) empMinMax->minHours = current->hours;
if (current->overtimeHrs < empMinMax->minOvertimeHrs) empMinMax->minOvertimeHrs = current->overtimeHrs;
if (current->grossPay < empMinMax->minGrossPay) empMinMax->minGrossPay = current->grossPay;
if (current->stateTax < empMinMax->minStateTax) empMinMax->minStateTax = current->stateTax;
if (current->fedTax < empMinMax->minFedTax) empMinMax->minFedTax = current->fedTax;
if (current->netPay < empMinMax->minNetPay) empMinMax->minNetPay = current->netPay;
// Update maximum values
if (current->wageRate > empMinMax->maxWage) empMinMax->maxWage = current->wageRate;
if (current->hours > empMinMax->maxHours) empMinMax->maxHours = current->hours;
if (current->overtimeHrs > empMinMax->maxOvertimeHrs) empMinMax->maxOvertimeHrs = current->overtimeHrs;
if (current->grossPay > empMinMax->maxGrossPay) empMinMax->maxGrossPay = current->grossPay;
if (current->stateTax > empMinMax->maxStateTax) empMinMax->maxStateTax = current->stateTax;
if (current->fedTax > empMinMax->maxFedTax) empMinMax->maxFedTax = current->fedTax;
if (current->netPay > empMinMax->maxNetPay) empMinMax->maxNetPay = current->netPay;
current = current->next;
}
}
/*****************************************************************************
* Function: printHeader
*
* Purpose: Prints the report header
*
* Parameters: none
*
* Returns: void
*****************************************************************************/
void printHeader(void)
{
printf("\n*** Pay Calculator ***\n"); printf("---------------------------------------------------------------------------------\n"); printf("Name Tax Clock# Wage Hours OT Gross State Fed Net\n"); printf(" State Pay Tax Tax Pay\n"); printf("---------------------------------------------------------------------------------\n"); }
/*****************************************************************************
* Function: printEmployee
*
* Purpose: Prints data for a single employee
*
* Parameters: emp - pointer to employee structure
*
* Returns: void
*****************************************************************************/
void printEmployee(struct employee *emp)
{
char fullName[52]; // First + last name + space
sprintf(fullName
, "%s %s", emp
->firstName
, emp
->lastName
);
printf("%-18s %-3s %06ld %5.2f %5.1f %4.1f %7.2f %5.2f %6.2f %7.2f\n", fullName,
emp->taxState,
emp->clockNumber,
emp->wageRate,
emp->hours,
emp->overtimeHrs,
emp->grossPay,
emp->stateTax,
emp->fedTax,
emp->netPay);
}
/*****************************************************************************
* Function: printSummary
*
* Purpose: Prints summary statistics
*
* Parameters: empTotals - pointer to totals structure
* empMinMax - pointer to min_max structure
* count - number of employees
*
* Returns: void
*****************************************************************************/
void printSummary(struct totals *empTotals, struct min_max *empMinMax, int count)
{
printf("---------------------------------------------------------------------------------\n"); printf("Totals: %5.2f %5.1f %4.1f %7.2f %5.2f %6.2f %7.2f\n", empTotals->totalWage, empTotals->totalHours, empTotals->totalOvertimeHrs,
empTotals->totalGrossPay, empTotals->totalStateTax, empTotals->totalFedTax, empTotals->totalNetPay);
if (count > 0) {
printf("Averages: %5.2f %5.1f %4.1f %7.2f %5.2f %6.2f %7.2f\n", empTotals->totalWage / count, empTotals->totalHours / count, empTotals->totalOvertimeHrs / count,
empTotals->totalGrossPay / count, empTotals->totalStateTax / count, empTotals->totalFedTax / count, empTotals->totalNetPay / count);
}
printf("Minimum: %5.2f %5.1f %4.1f %7.2f %5.2f %6.2f %7.2f\n", empMinMax->minWage, empMinMax->minHours, empMinMax->minOvertimeHrs,
empMinMax->minGrossPay, empMinMax->minStateTax, empMinMax->minFedTax, empMinMax->minNetPay);
printf("Maximum: %5.2f %5.1f %4.1f %7.2f %5.2f %6.2f %7.2f\n", empMinMax->maxWage, empMinMax->maxHours, empMinMax->maxOvertimeHrs,
empMinMax->maxGrossPay, empMinMax->maxStateTax, empMinMax->maxFedTax, empMinMax->maxNetPay);
}