//********************************************************
//
// Assignment 10 - Linked Lists, Typedef, and Macros
//
// Name: John Semenuk
//
// Class: C Programming, Spring 2026
//
// Date: April 20, 2026
//
//********************************************************
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#define STD_HOURS 40.0
#define OT_RATE 1.5
#define MA_TAX_RATE 0.05
#define NH_TAX_RATE 0.0
#define VT_TAX_RATE 0.06
#define CA_TAX_RATE 0.07
#define DEFAULT_STATE_TAX_RATE 0.08
#define FED_TAX_RATE 0.25
#define FIRST_NAME_SIZE 10
#define LAST_NAME_SIZE 10
#define TAX_STATE_SIZE 3
// ================= MACROS =================
#define CALC_OT_HOURS(theHours) ((theHours > STD_HOURS) ? theHours - STD_HOURS : 0)
#define CALC_STATE_TAX(thePay,theRate) (thePay * theRate)
#define CALC_FED_TAX(thePay) (thePay * FED_TAX_RATE)
#define CALC_NET_PAY(thePay,theStateTax,theFedTax) \
(thePay - (theStateTax + theFedTax))
#define CALC_NORMAL_PAY(rate,hours,ot) \
(rate * (hours - ot))
#define CALC_OT_PAY(rate,ot) \
(ot * (OT_RATE * rate))
#define CALC_MIN(value,currentMin) ((value < currentMin) ? value : currentMin)
#define CALC_MAX(value,currentMax) ((value > currentMax) ? value : currentMax)
// ================= STRUCTS =================
struct name {
char firstName[FIRST_NAME_SIZE];
char lastName[LAST_NAME_SIZE];
};
typedef struct employee {
struct name empName;
char taxState[TAX_STATE_SIZE];
long clockNumber;
float wageRate;
float hours;
float overtimeHrs;
float grossPay;
float stateTax;
float fedTax;
float netPay;
struct employee *next;
} EMPLOYEE;
typedef struct totals {
float total_wageRate;
float total_hours;
float total_overtimeHrs;
float total_grossPay;
float total_stateTax;
float total_fedTax;
float total_netPay;
} TOTALS;
typedef struct min_max {
float min_wageRate;
float min_hours;
float min_overtimeHrs;
float min_grossPay;
float min_stateTax;
float min_fedTax;
float min_netPay;
float max_wageRate;
float max_hours;
float max_overtimeHrs;
float max_grossPay;
float max_stateTax;
float max_fedTax;
float max_netPay;
} MIN_MAX;
// ================= PROTOTYPES =================
EMPLOYEE * getEmpData(void);
int isEmployeeSize(EMPLOYEE *head_ptr);
void calcOvertimeHrs(EMPLOYEE *head_ptr);
void calcGrossPay(EMPLOYEE *head_ptr);
void calcStateTax(EMPLOYEE *head_ptr);
void calcFedTax(EMPLOYEE *head_ptr);
void calcNetPay(EMPLOYEE *head_ptr);
void calcEmployeeTotals(EMPLOYEE *head_ptr, TOTALS *totals);
void calcEmployeeMinMax(EMPLOYEE *head_ptr, MIN_MAX *minmax);
void printHeader(void);
void printEmp(EMPLOYEE *head_ptr);
void printEmpStatistics(TOTALS *totals, MIN_MAX *minmax, int size);
// ================= MAIN =================
int main() {
EMPLOYEE *head_ptr;
int size;
TOTALS totals = {0};
MIN_MAX minmax;
head_ptr = getEmpData();
size = isEmployeeSize(head_ptr);
if (size <= 0) {
printf("\nNo employees to process\n"); return 0;
}
calcOvertimeHrs(head_ptr);
calcGrossPay(head_ptr);
calcStateTax(head_ptr);
calcFedTax(head_ptr);
calcNetPay(head_ptr);
calcEmployeeTotals(head_ptr, &totals);
calcEmployeeMinMax(head_ptr, &minmax);
printHeader();
printEmp(head_ptr);
printEmpStatistics(&totals, &minmax, size);
printf("\n\n *** End of Program *** \n"); return 0;
}
// ================= FUNCTIONS =================
EMPLOYEE * getEmpData(void)
{
EMPLOYEE
*head_ptr
= malloc(sizeof(EMPLOYEE
)); EMPLOYEE *current_ptr = head_ptr;
char answer[10];
while (1)
{
scanf("%s", current_ptr
->empName.
firstName);
scanf("%s", current_ptr
->empName.
lastName);
scanf("%s", current_ptr
->taxState
);
scanf("%ld", ¤t_ptr
->clockNumber
);
scanf("%f", ¤t_ptr
->wageRate
);
scanf("%f", ¤t_ptr
->hours
);
printf("More employees? (y/n): ");
current_ptr->next = NULL;
break;
}
current_ptr
->next
= malloc(sizeof(EMPLOYEE
)); current_ptr = current_ptr->next;
}
return head_ptr;
}
int isEmployeeSize(EMPLOYEE *head_ptr)
{
int count = 0;
while (head_ptr)
{
count++;
head_ptr = head_ptr->next;
}
return count;
}
void calcOvertimeHrs(EMPLOYEE *head_ptr)
{
while (head_ptr)
{
head_ptr->overtimeHrs = CALC_OT_HOURS(head_ptr->hours);
head_ptr = head_ptr->next;
}
}
void calcGrossPay(EMPLOYEE *head_ptr)
{
while (head_ptr)
{
float normal = CALC_NORMAL_PAY(head_ptr->wageRate, head_ptr->hours, head_ptr->overtimeHrs);
float ot = CALC_OT_PAY(head_ptr->wageRate, head_ptr->overtimeHrs);
head_ptr->grossPay = normal + ot;
head_ptr = head_ptr->next;
}
}
void calcStateTax(EMPLOYEE *head_ptr)
{
while (head_ptr)
{
if (!strcmp(head_ptr
->taxState
, "MA")) head_ptr->stateTax = CALC_STATE_TAX(head_ptr->grossPay, MA_TAX_RATE);
else if (!strcmp(head_ptr
->taxState
, "NH")) head_ptr->stateTax = CALC_STATE_TAX(head_ptr->grossPay, NH_TAX_RATE);
else if (!strcmp(head_ptr
->taxState
, "VT")) head_ptr->stateTax = CALC_STATE_TAX(head_ptr->grossPay, VT_TAX_RATE);
else if (!strcmp(head_ptr
->taxState
, "CA")) head_ptr->stateTax = CALC_STATE_TAX(head_ptr->grossPay, CA_TAX_RATE);
else
head_ptr->stateTax = CALC_STATE_TAX(head_ptr->grossPay, DEFAULT_STATE_TAX_RATE);
head_ptr = head_ptr->next;
}
}
void calcFedTax(EMPLOYEE *head_ptr)
{
while (head_ptr)
{
head_ptr->fedTax = CALC_FED_TAX(head_ptr->grossPay);
head_ptr = head_ptr->next;
}
}
void calcNetPay(EMPLOYEE *head_ptr)
{
while (head_ptr)
{
head_ptr->netPay = CALC_NET_PAY(head_ptr->grossPay,
head_ptr->stateTax,
head_ptr->fedTax);
head_ptr = head_ptr->next;
}
}
void calcEmployeeTotals(EMPLOYEE *head_ptr, TOTALS *t)
{
while (head_ptr)
{
t->total_wageRate += head_ptr->wageRate;
t->total_hours += head_ptr->hours;
t->total_overtimeHrs += head_ptr->overtimeHrs;
t->total_grossPay += head_ptr->grossPay;
t->total_stateTax += head_ptr->stateTax;
t->total_fedTax += head_ptr->fedTax;
t->total_netPay += head_ptr->netPay;
head_ptr = head_ptr->next;
}
}
void calcEmployeeMinMax(EMPLOYEE *head_ptr, MIN_MAX *m)
{
EMPLOYEE *current = head_ptr;
*m = (MIN_MAX){
current->wageRate, current->hours, current->overtimeHrs,
current->grossPay, current->stateTax, current->fedTax, current->netPay,
current->wageRate, current->hours, current->overtimeHrs,
current->grossPay, current->stateTax, current->fedTax, current->netPay
};
current = current->next;
while (current)
{
m->min_wageRate = CALC_MIN(current->wageRate, m->min_wageRate);
m->max_wageRate = CALC_MAX(current->wageRate, m->max_wageRate);
m->min_hours = CALC_MIN(current->hours, m->min_hours);
m->max_hours = CALC_MAX(current->hours, m->max_hours);
m->min_overtimeHrs = CALC_MIN(current->overtimeHrs, m->min_overtimeHrs);
m->max_overtimeHrs = CALC_MAX(current->overtimeHrs, m->max_overtimeHrs);
m->min_grossPay = CALC_MIN(current->grossPay, m->min_grossPay);
m->max_grossPay = CALC_MAX(current->grossPay, m->max_grossPay);
m->min_stateTax = CALC_MIN(current->stateTax, m->min_stateTax);
m->max_stateTax = CALC_MAX(current->stateTax, m->max_stateTax);
m->min_fedTax = CALC_MIN(current->fedTax, m->min_fedTax);
m->max_fedTax = CALC_MAX(current->fedTax, m->max_fedTax);
m->min_netPay = CALC_MIN(current->netPay, m->min_netPay);
m->max_netPay = CALC_MAX(current->netPay, m->max_netPay);
current = current->next;
}
}
void printHeader(void)
{
printf("\n*** Pay Calculator ***\n"); }
void printEmp(EMPLOYEE *head_ptr)
{
while (head_ptr)
{
printf("\n%-10s %-10s %ld %.2f %.1f %.1f %.2f %.2f %.2f %.2f", head_ptr->empName.firstName,
head_ptr->empName.lastName,
head_ptr->clockNumber,
head_ptr->wageRate,
head_ptr->hours,
head_ptr->overtimeHrs,
head_ptr->grossPay,
head_ptr->stateTax,
head_ptr->fedTax,
head_ptr->netPay);
head_ptr = head_ptr->next;
}
}
void printEmpStatistics(TOTALS *t, MIN_MAX *m, int size)
{
printf("\n\nTotals Gross: %.2f", t
->total_grossPay
); printf("\nAverage Gross: %.2f", t
->total_grossPay
/ size
);
printf("\nMin Gross: %.2f", m
->min_grossPay
); printf("\nMax Gross: %.2f", m
->max_grossPay
); }