Click here to Skip to main content
15,881,715 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
Hello guys and good evening!

The problem that I have been having with my code is that my totals and averages do not show the correct values that they should be! Everything else in my program works so far, the check headers, QSort, formatting for employee data, and displaying correct information entered for everything else.

You can see the program in action here:
Part 1
Part 2
Part 3
Part 4

I changed the order of which the information is stored, since payrate and hours were accidentally the opposite way. Also bumped up my print totals and print averages before the print checks.

Now without further ado, my source code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

typedef short BOOLEAN;
typedef char STR15[15 + 1];
typedef char STR10[10 + 1];
typedef struct PayRecord
{
	STR15 LastName;
	STR10 FirstName;
	float hours, payrate, deferred, gross, fedtax, statetax, ssitax, net;
	float reghrs, ovthrs;
	float totreg, totovt, totrate, totgross, totfed, totstate, totssi, totdefr, totnet;
} PayRecord;

#define FEDTAXRATE 0.15
#define STATETAXRATE 0.07
#define SSITAXRATE 0.0775
#define MAXEMPLOYEES 5
#define TRUE 1
#define FALSE 0

#define HEADLINE1       "Employee         Pay    Reg Hrs  Gross    Fed    SSI    Net\n"
#define HEADLINE2       "Name             Rate   Ovt Hrs  Pay     State   Defr   Pay\n"
#define HEADLINE3       "=========        ====== ======= ======= ======= ====== =======\n"
#define EMPLOYEEREPORT  "%-16s %5.2f    %5.2f %7.2f  %6.2f %6.2f %7.2f\n"
#define EMPLOYEEREPORT2 "                          %5.2f          %6.2f %6.2f\n\n"
#define BREAK           "==============================================================\n"
#define TOTALS1         "Totals           %5.2f   %6.2f %6.2f  %6.2f %6.2f %7.2f\n"
#define TOTALS2         "                         %6.2f           %5.2f %6.2f\n\n"
#define AVERAGES1       "Averages         %5.2f   %6.2f  %5.2f  %6.2f %6.2f %7.2f\n"
#define AVERAGES2       "                         %6.2f           %5.2f %6.2f\n\n"

#define BLANK	"*							   *\n"
#define BORDER  "************************************************************\n"
#define HEADER  "*				Check No %3d		   *\n"
#define HEADER2 "*   Sabre Corporation					   *\n"
#define HEADER3 "*   15790 West Henness lane				   *\n"
#define HEADER4 "*   New Corio, New Mexico 65790				   *\n"
#define HEADER5 "*   Pay to the Order of					   *\n"
#define HEADER6 "*   %-16s					   *\n"
#define HEADER7 "*   The Sum Nine Hundred Ninety-Nine and XX/100 Dollars    *\n"
#define HEADER8 "*   Reference: %-16s				   *\n"

#define STUB 	"*   Check No %3d					   *\n"
#define STUB2	"*   %-16s	   Reg Pay		Fed Tax	   *\n"
#define STUB3	"*   Address		   Ovt Pay		State Tax  *\n"
#define STUB4	"*   City, State		   Gross Pay		SSI Tax    *\n"
#define STUB5	"*   Zip			   Net Pay		Tax Total  *\n"

void PrintHeadings(FILE *reportFile)
{
	fprintf(reportFile, HEADLINE1);
	fprintf(reportFile, HEADLINE2);
	fprintf(reportFile, HEADLINE3);
}
void InitAccumulators(PayRecord EmployeeData[], int maxemployees)
{
	EmployeeData[MAXEMPLOYEES - 1].totreg = 0;
	EmployeeData[MAXEMPLOYEES - 1].totovt = 0;
	EmployeeData[MAXEMPLOYEES - 1].totrate = 0;
	EmployeeData[MAXEMPLOYEES - 1].totgross = 0;
	EmployeeData[MAXEMPLOYEES - 1].totfed = 0;
	EmployeeData[MAXEMPLOYEES - 1].totstate = 0;
	EmployeeData[MAXEMPLOYEES - 1].totssi = 0;
	EmployeeData[MAXEMPLOYEES - 1].totdefr = 0;
	EmployeeData[MAXEMPLOYEES - 1].totnet = 0;
}
void InputEmployeeData(PayRecord EmployeeData[], int count)// 3.3
{
	printf("Please enter your first and last name: ");
	scanf("%s%s", EmployeeData[count].FirstName, EmployeeData[count].LastName);

	printf("Please enter hours, payrate, and deferred amount: ");
	scanf("%f%f%f", &EmployeeData[count].hours, &EmployeeData[count].payrate, &EmployeeData[count].deferred);
	printf("\n");
}
void QSortEmployee(PayRecord EmployeeData[], int start, int finish)
{
	int left = start,
		right = finish;
	char * pivot = EmployeeData[(start + finish) / 2].LastName;

	while (left < right)
	{
		while ((strcmp(EmployeeData[left].LastName, pivot) < 0) && (left < right))
		{
			left++;
		}
		while ((strcmp(EmployeeData[right].LastName, pivot) > 0) && (right > left))
		{
			right--;
		}
		if (left <= right)
		{
			PayRecord tempEmployee = EmployeeData[left];
			EmployeeData[left] = EmployeeData[right];
			EmployeeData[right] = tempEmployee;
			left++;
			right--;
		}
	}
	if (start < finish)
	{
		QSortEmployee(EmployeeData, start, right);
	}
	if (left < finish)
	{
		QSortEmployee(EmployeeData, left, finish);
	}
}
float CalculateGross(PayRecord EmployeeData[], int count) // 3.4
{
	return (EmployeeData[count].hours <= 40) ? EmployeeData[count].hours * EmployeeData[count].payrate :
		EmployeeData[count].payrate * 40 + (EmployeeData[count].hours - 40) * 1.5 * EmployeeData[count].payrate;
}

void CalculateHours(PayRecord EmployeeData[], int count)
{
	if (EmployeeData[count].hours <= 40)
	{
		EmployeeData[count].reghrs = EmployeeData[count].hours;
		EmployeeData[count].ovthrs = 0;
	}
	else
	{
		EmployeeData[count].reghrs = 40;
		EmployeeData[count].ovthrs = (EmployeeData[count].hours - 40);
	}
}
float CalculateNet(PayRecord EmployeeData[], int count)
{
	return EmployeeData[count].gross - (EmployeeData[count].fedtax + EmployeeData[count].statetax + EmployeeData[count].ssitax + EmployeeData[count].deferred);
}
void AddAccumulators(PayRecord EmployeeData[], int count, int maxemployees)
{
	EmployeeData[MAXEMPLOYEES - 1].totreg = EmployeeData[MAXEMPLOYEES - 1].totreg + EmployeeData[count].reghrs;
	EmployeeData[MAXEMPLOYEES - 1].totovt = EmployeeData[MAXEMPLOYEES - 1].totovt + EmployeeData[count].ovthrs;
	EmployeeData[MAXEMPLOYEES - 1].totrate = EmployeeData[MAXEMPLOYEES - 1].totrate + EmployeeData[count].payrate;
	EmployeeData[MAXEMPLOYEES - 1].totgross = EmployeeData[MAXEMPLOYEES - 1].totgross + EmployeeData[count].gross;
	EmployeeData[MAXEMPLOYEES - 1].totfed = EmployeeData[MAXEMPLOYEES - 1].totfed + EmployeeData[count].fedtax;
	EmployeeData[MAXEMPLOYEES - 1].totstate = EmployeeData[MAXEMPLOYEES - 1].totstate + EmployeeData[count].statetax;
	EmployeeData[MAXEMPLOYEES - 1].totssi = EmployeeData[MAXEMPLOYEES - 1].totssi + EmployeeData[count].ssitax;
	EmployeeData[MAXEMPLOYEES - 1].totdefr = EmployeeData[MAXEMPLOYEES - 1].totdefr + EmployeeData[count].deferred;
	EmployeeData[MAXEMPLOYEES - 1].totnet = EmployeeData[MAXEMPLOYEES - 1].totnet + EmployeeData[count].net;
}

void showReport(FILE *reportFile, char *FullName, PayRecord EmployeeData[], int count) //3.8
{
	printf(HEADLINE1);
	printf(HEADLINE2);
	printf(HEADLINE3);
	printf(EMPLOYEEREPORT, FullName, EmployeeData[count].payrate, EmployeeData[count].reghrs, EmployeeData[count].gross, EmployeeData[count].fedtax, EmployeeData[count].ssitax, EmployeeData[count].net);
	printf(EMPLOYEEREPORT2, EmployeeData[count].ovthrs, EmployeeData[count].statetax, EmployeeData[count].deferred);
	fprintf(reportFile, EMPLOYEEREPORT, FullName, EmployeeData[count].payrate, EmployeeData[count].reghrs, EmployeeData[count].gross, EmployeeData[count].fedtax, EmployeeData[count].ssitax, EmployeeData[count].net);
	fprintf(reportFile, EMPLOYEEREPORT2, EmployeeData[count].ovthrs, EmployeeData[count].statetax, EmployeeData[count].deferred);
}
void printTotals(FILE *reportFile, PayRecord EmployeeData[], int maxemployees)
{
	printf(BREAK);
	printf(TOTALS1, EmployeeData[MAXEMPLOYEES - 1].totrate, EmployeeData[MAXEMPLOYEES - 1].totreg, EmployeeData[MAXEMPLOYEES - 1].totgross, EmployeeData[MAXEMPLOYEES - 1].totfed, EmployeeData[MAXEMPLOYEES - 1].totssi, EmployeeData[MAXEMPLOYEES - 1].totnet);
	printf(TOTALS2, EmployeeData[MAXEMPLOYEES - 1].totovt, EmployeeData[MAXEMPLOYEES - 1].totstate, EmployeeData[MAXEMPLOYEES - 1].totdefr);
	fprintf(reportFile, BREAK);
	fprintf(reportFile, TOTALS1, EmployeeData[MAXEMPLOYEES - 1].totrate, EmployeeData[MAXEMPLOYEES - 1].totreg, EmployeeData[MAXEMPLOYEES - 1].totgross, EmployeeData[MAXEMPLOYEES - 1].totfed, EmployeeData[MAXEMPLOYEES - 1].totssi, EmployeeData[MAXEMPLOYEES - 1].totnet);
	fprintf(reportFile, TOTALS2, EmployeeData[MAXEMPLOYEES - 1].totovt, EmployeeData[MAXEMPLOYEES - 1].totstate, EmployeeData[MAXEMPLOYEES - 1].totdefr);
}
void printAverages(FILE *reportFile, int maxemployees, PayRecord EmployeeData[])
{
	printf(AVERAGES1, (EmployeeData[MAXEMPLOYEES - 1].totrate / MAXEMPLOYEES), (EmployeeData[MAXEMPLOYEES - 1].totreg / MAXEMPLOYEES), (EmployeeData[MAXEMPLOYEES - 1].totgross / MAXEMPLOYEES), (EmployeeData[MAXEMPLOYEES - 1].totfed / MAXEMPLOYEES), (EmployeeData[MAXEMPLOYEES - 1].totssi / MAXEMPLOYEES), (EmployeeData[MAXEMPLOYEES - 1].totnet / MAXEMPLOYEES));
	printf(AVERAGES2, (EmployeeData[MAXEMPLOYEES - 1].totovt / MAXEMPLOYEES), (EmployeeData[MAXEMPLOYEES - 1].totstate / MAXEMPLOYEES), (EmployeeData[MAXEMPLOYEES - 1].totdefr / MAXEMPLOYEES));
	fprintf(reportFile, AVERAGES1, (EmployeeData[MAXEMPLOYEES - 1].totrate / MAXEMPLOYEES), (EmployeeData[MAXEMPLOYEES - 1].totreg / MAXEMPLOYEES), (EmployeeData[MAXEMPLOYEES - 1].totgross / MAXEMPLOYEES), (EmployeeData[MAXEMPLOYEES - 1].totfed / MAXEMPLOYEES), (EmployeeData[MAXEMPLOYEES - 1].totssi / MAXEMPLOYEES), (EmployeeData[MAXEMPLOYEES - 1].totnet / MAXEMPLOYEES));
	fprintf(reportFile, AVERAGES2, (EmployeeData[MAXEMPLOYEES - 1].totovt / MAXEMPLOYEES), (EmployeeData[MAXEMPLOYEES - 1].totstate / MAXEMPLOYEES), (EmployeeData[MAXEMPLOYEES - 1].totdefr / MAXEMPLOYEES));
}
float CalcFedtax(PayRecord EmployeeData[], int count) // 3.5.1
{
	return (EmployeeData[count].gross - EmployeeData[count].deferred)*FEDTAXRATE;
}
float CalcStatetax(PayRecord EmployeeData[], int count) // 3.5.2
{
	return EmployeeData[count].fedtax * STATETAXRATE;
}
float CalcSSItax(PayRecord EmployeeData[], int count) // 3.5.3
{
	return (EmployeeData[count].gross - EmployeeData[count].deferred)*SSITAXRATE;
}
void CalculateTaxes(PayRecord EmployeeData[], int count) //3.5
{
	EmployeeData[count].fedtax = CalcFedtax(EmployeeData, count); // call 3.5.1
	EmployeeData[count].statetax = CalcStatetax(EmployeeData, count); // call 3.5.2
	EmployeeData[count].ssitax = CalcSSItax(EmployeeData, count); // call 3.5.3
}
//====================

void printCheckHeader(PayRecord EmployeeData[], char *CheckName, int chkNo, char *refCode, int count)
{
	printf(BORDER);
	printf(HEADER, chkNo);
	printf(BLANK);
	printf(HEADER2);
	printf(HEADER3);
	printf(HEADER4);
	printf(BLANK);
	printf(BLANK);
	printf(HEADER5);
	printf(BLANK);
	printf(HEADER6, CheckName);
	printf(BLANK);
	printf(HEADER7);
	printf(BLANK);
	printf(BLANK);
	printf(HEADER8, refCode);
	printf(BLANK);
	printf(BLANK);
	printf(BORDER);
}
void printCheckStub(PayRecord EmployeeData[], char *CheckName, int chkNo, int count)
{
	printf(STUB, chkNo);
	printf(BLANK);
	printf(STUB2, CheckName);
	printf(STUB3);
	printf(STUB4);
	printf(STUB5);
	printf(BLANK);
	printf(BLANK);
	printf(BORDER);
	printf("\n");
}
BOOLEAN isVowel(char aChar)
{
	switch (toupper(aChar)) //<ctype.h>
	{
	case 'A':
	case 'E':
	case 'I':
	case 'O':
	case 'U': return TRUE; break;
	default: return FALSE;
	}
}
char *generateRefCode(PayRecord EmployeeData[], int chkNo, int count)
{

	static char tempStr[15 + 10 + 1];
	char buffer[10 + 1];
	int i, j = 1;

	//This loop is used to clear the string everytime generateRefCode is called
	for (i = 0; i < 26; i++)
	{
		tempStr[i] = 0;
	}
	//tempStr[0] = lastname[0]; // Needs to put the first letter into the temporary string.
	tempStr[0] = toupper(EmployeeData[count].LastName[0]);
	// This should be the first address that holds the first letter of the last name.
	// LOOP
	// Need to get through all the characters in the lastname.
	// Check if the letter is a vowl. If it is, add to the temporary string, else omit it.
	// ENDLOOP
	for (i = 1; i < strlen(EmployeeData[count].LastName); i++)
	{
		if (!isVowel(EmployeeData[count].LastName[i]))
		{
			tempStr[j++] = toupper(EmployeeData[count].LastName[i]);
		}
	}

	sprintf(buffer, "%d", chkNo);
	//sprintf is used to make int chkNo into a string using a char buffer
	strcat(tempStr, buffer);
	tempStr[j + 3] = 0;
	// add string terminator, adds the the current subscript+3 because we add
	// 3 numbers to the end of the string so that it adds the string terminator
	// to the end of the string.
	return tempStr;
}

int main(void)
{
	PayRecord EmployeeData[MAXEMPLOYEES];
	char FullName[15 + 10 + 1];
	char CheckName[15 + 10 + 1];
	char *refCode;
	int count;
	int chkNo = 100;
	FILE *reportFile; // Read as "reportFile is a pointer to a file"

	reportFile = fopen("./report.txt", "wt");// open the file for "write-mode" access

	if (reportFile == NULL)// Test if file DID NOT open, exit.
	{
		printf(" report file open failed ...\n");
		fflush(stdin);
		exit(-30); //reqs <stdlib.h>
	}

	PrintHeadings(reportFile);//Call 3.1
	InitAccumulators(EmployeeData, (MAXEMPLOYEES - 1));//call 3.2
	for (count = 0; count < MAXEMPLOYEES; count++)
	{
		InputEmployeeData(EmployeeData, count);
	}

	QSortEmployee(EmployeeData, 0, (MAXEMPLOYEES - 1));

	for (count = 0; count < MAXEMPLOYEES; count++)
	{
		strcpy(FullName, EmployeeData[count].LastName);
		strcat(FullName, ", ");
		strcat(FullName, EmployeeData[count].FirstName);
		EmployeeData[count].gross = CalculateGross(EmployeeData, count);// Call 3.4
		//CalculateHours() does not actually calculate any hours
		//It seperates the hours into regular hours and overtime hours
		CalculateHours(EmployeeData, count);// Call 3.4.1
		CalculateTaxes(EmployeeData, count); // call 3.5
		EmployeeData[count].net = CalculateNet(EmployeeData, count);//call 3.6
		AddAccumulators(EmployeeData, count, (MAXEMPLOYEES - 1));//call 3.7
		showReport(reportFile, FullName, EmployeeData, count);//call 3.8
	}

	printTotals(reportFile, EmployeeData, (MAXEMPLOYEES - 1));//call 3.8.1
	printAverages(reportFile, (MAXEMPLOYEES - 1), EmployeeData);//call 3.8.2

	for (count = 0; count < MAXEMPLOYEES; count++)
	{
		refCode = generateRefCode(EmployeeData, chkNo, count);
		strcpy(CheckName, EmployeeData[count].FirstName);
		strcat(CheckName, " ");
		strcat(CheckName, EmployeeData[count].LastName);
		printCheckHeader(EmployeeData, CheckName, chkNo, refCode, count);
		printCheckStub(EmployeeData, CheckName, chkNo, count);
		chkNo++;
	}

	fclose(reportFile);// Close file
	fflush(stdin);
	getchar();
	return 0;
}


Thanks for the help in advance!
Posted
Updated 17-May-14 18:28pm
v2
Comments
OriginalGriff 18-May-14 1:03am    
Do you think I want to wade through your whole program trying to work out what is relevant to the problem in hand and what isn't? Or that I want to go off an look at a couple of images because you are too lazy to show me what results you get from what inputs that are again relevant?

Because if so, you are wrong.
Edit your question. Show me what input generate what results, and what results you expected.
Then just show me the relevant code fragments.

Help us to help you!

1 solution

Sorry I had laugh at your expense, you do all this work and miss the basic.

One comment for the love of god make a separate record for the totals it's not hard
EmployeeData TotalsRecord; 

It will the stop you doing the stupid thing you have done which is to use the last employee record to hold the totals in and then Qsort it later so it's not last anymore :-)

See the problem

InitAccumulators => zeros the last record (MAXEMPLOYEES - 1)
AddAccumulators => You add all the totals to (MAXEMPLOYEES - 1)
QSortEmployee(EmployeeData, 0, (MAXEMPLOYEES - 1)); => You then Qsort the data including your totals record :-)

The negative numbers are because you don't zero any of the other fields and so they just have rubbish in them
 
Share this answer
 
v3
Comments
xFerii 18-May-14 3:10am    
leon de boer, thank you so much! I was having so much trouble figuring out why possibly it wouldn't compute the totals and averages, makes so much sense now! I'm going to assume you want me to use the TotalsRecord to compute the averages as well so those aren't also rubbish from the rubbish total values due to using the (MAXEMPLOYEES - 1). :)

I'll let you know how it goes, working on it now!
xFerii 18-May-14 3:43am    
THANK YOU SO MUCH LEON DE BOER! I defined another TOTALSRECORD as 5 and now that I replaced MAXEMPLOYEES with it, my program didn't give me junk for my totals and averages! It gave the ACTUAL values! So happy right now :D

Here's it working: http://i.imgur.com/Fz3QlSM.png
leon de boer 18-May-14 10:15am    
You are welcome one final comment I hope you restricted the QSort down to the number of actual valid customer records there is no point sorting what is empty and unused customer records it just wastes time.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900