Payroll/Final Program Help

I am having trouble getting the arrays to read into the program. will print the cout statements, but is not reading the arrays from the data file and printing those out. Thanks for any help.


THANKS FOR ANY HELP!!!!!

#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>

using namespace std;

const double Federal = 0.08;
const double State = 0.03;
const double Social = 0.02;

double Deductionsfn(double State, double Federal, double Social, double deductions, double ytdGross, double gross);

int main()
{
string lname[10];
string fname[10];
string paytype[10];
double rate[10];
double ytdGross[10];
double gross[10];
double deductions[10];
double netpay[10];

string filename;

ifstream din;
ofstream dout;

int i = 0;
int numOfEmp = 0;

cout << "Please type in the file name." << endl;
cin >> filename;

din.open(filename.c_str());

if (!din)
{
cout << "File Not Found." << endl;
cout << "Try Again." << endl;
cin >> filename;
din.clear();
din.open(filename.c_str());
}

din >> fname[i];

while (!din.eof())
{
din >> fname[i];
din >> paytype[i];
din >> rate[i];
din >> ytdGross[i];
i++;
din >> lname[i];
}

numOfEmp = i;
int choice;
bool menu = true;

double hours;
double overtime;

while (menu != false)
{
cout << "1. Run Weekly Payroll." << endl;
cout << "2. Print Weekly Payroll." << endl;
cout << "3. Exit." << endl;

cout << "Please enter your choice." << endl;
cin >> choice;

switch (choice)
{
case 1: "Run Weekly Payroll.";
if (paytype[i] == "S")
{
gross[i] = (rate[i] / 12) / 4;
ytdGross[i] = ytdGross[i] + gross[i];
}
if (paytype[i] == "H")
{
cout << "How many hours did" << lname[i] << "," << fname[i] << "work?" << endl;
cin >> hours;

cout << endl;

if (hours >= 40)
{
overtime = (hours - 40) * (rate[i] * 1.5);
ytdGross[i] = (rate[i] * 40) + overtime;
ytdGross[i] = ytdGross[i] + gross[i];
}
else if (hours < 40)
{
ytdGross[i] = (rate[i] * hours);
ytdGross[i] = ytdGross[i] + gross[i];
}
}

cout << "Weekly Gross Pay" << endl;
cout << "--------------------" << endl;
for (int i = 0; i < 10; i++)
{
if (lname[i] == "")
break;
cout << lname[i] << "," << fname[i] << "--$" << ytdGross[i] << endl;
}

//Total Deductions
cout << endl;
cout << "Total Deductions" << endl;
cout << "--------------------" << endl;
for (int i = 0; i < 10; i++)
{
if (lname[i] == "")
break;

deductions[i] = Deductionsfn(State, Federal, Social, deductions[i], ytdGross[i], gross[i]);

cout << lname[i] << "," << fname[i] << "--$" << deductions[i] << endl;

}

//Net Pay
cout << endl;
cout << "Net Pay" << endl;

cout << "--------------------" << endl;

for (int i = 0; i < 10; i++)
{
if (lname[i] == "")
break;

netpay[i] = ytdGross[i] - deductions[i];

cout << lname[i] << "," << fname[i] << "--$" << netpay[i] << endl;
}

//Check
for (int i = 0; i < 10; i++)
{
if (lname[i] == "")
break;
cout <<
"*************************************************************************" << endl;
cout << "12432 Somewhere St." << endl;

cout << setw(50) << left << setfill('_') << "Russellville, AR 72802"
<< setw(13) << right << setfill('_') << "1/23/2020"
<< setw(12) << right << setfill('_') << "Date" << endl;
cout << endl << endl;

cout << setw(7) << left << setfill('_') << "Pay"
<< setw(49) << left << setfill('_') << lname[i] << "," << fname[i] << " $"
<< setprecision(2) << fixed << showpoint << setw(16) << right <<
setfill('_') << netpay[i] << endl;

cout << endl << endl;

int dollars[10];
int cents[10];
double altercents[10];
double alterdollars[10];
float editnet[10];

editnet[i] = netpay[i];
dollars[i] = editnet[i];
altercents[i] = editnet[i] - dollars[i];
alterdollars[i] = editnet[i] - altercents[i];

cout << setw(18) << right << setfill('_') << alterdollars[i]
<< "_Dollars_&_" << setw(3) << left << setfill('_') << altercents[i]
<< setw(17) << left << setfill('_') << "Cents" << endl;
cout << endl << endl;

cout << setw(45) << left << setfill('_') << "Bank of Foundations I" <<
setw(29) << left << setfill('_') << "_" << endl;
cout << setw(74) << setfill('*') << endl;

cout << endl << endl;
}
break;

case 2:
cout << endl << endl;

cout << "Lastname" << setw(30)
<< "Firstname" << setw(30)
<< "Rate / Salary" << endl
<<
"__________________________________________________________________" << endl;

for (int i = 0; i < 10; i++)
{
if (lname[i] == "")
break;

if (paytype[i] == "S")
{
cout << lname[i] << setw(30) << fname[i] << setw(30) << rate[i] << endl;
}
}

for (int i = 0; i < 10; i++)
{
if (lname[i] == "")
break;

if (lname[i] == "H")
{
cout << lname[i] << setw(30) << fname[i] << setw(30) << rate[i] << endl;
}
}
break;

case 3:
menu = false;
break;
}

return 0;
}
}
double Deductionsfn(double State, double Federal, double Social, double deductions, double ytdGross, double gross)
{
double afState, afFederal, afSocial;

afState = ytdGross * State;
afFederal = ytdGross * Federal;

if (gross < 30000)
{
afSocial = ytdGross * Social;
deductions = (afState + afFederal + afSocial);
}
else if (gross > 30000)
{
deductions = afState + afFederal;
}

return deductions;
}


Surely since this is your "final" you've studied classes/structures. You really should consider using them, along with std::vector instead of the arrays.

What does your input file look like (please post a small sample inside code tags to preserve formatting).

@kmheflin712

1
2
3
4
5
6
7
8
9
10
11
12
13
14
din >> fname[i]; // Why??

while (!din.eof())
{
din >> fname[i];
din >> paytype[i];
din >> rate[i];
din >> ytdGross[i];
i++; // Why increase i BEFORE assigning lname[i]??
// fname and lname won't match up anymore PLUS you'll be out-of-bounds in array
// after 10th name
din >> lname[i];
}
Hello kmheflin712,


PLEASE ALWAYS USE CODE TAGS (the <> formatting button), to the right of this box, when posting code.

Along with the proper indenting it makes it easier to read your code and also easier to respond to your post.

http://www.cplusplus.com/articles/jEywvCM9/
http://www.cplusplus.com/articles/z13hAqkS/

Hint: You can edit your post, highlight your code and press the <> formatting button.
You can use the preview button at the bottom to see how it looks.

I found the second link to be the most help.


Right now you have about 250 lines of unintended code to read and it is very difficult. Not many will take the time to read it.

I am having trouble getting the arrays to read into the program.
Amazing, I am too. The difference is that you have a file to read and I do not.

As jlb noted post the input file along with the file name so that everyone can use the same information. As of now I can not test the program because there is nothing to read.

The other things I have noticed I will have to get to shortly.

Andy
Hello kmheflin712,

I agree with jlb the program would benefit immensely from the use of a struct and "std::vector. Using a struct would condense most of the arrays down to just one, but a vector would work better than an array.

For the most part you are goo down to the point where you ask the user for a file name. except for using namespace std; // <--- Best not to use. and I would add constexpr size_t MAXSIZE{ 10 }; then when you define your arrays std::string lname[MAXSIZE];. This way if you need to change the size of your arrays it only needs done in one place and not the eight + arrays that you have.

You are asking a lot of the user to remember the file name to use when you ask for the file name. It would be nice to list the file names that can be used so the user can see what there is to choose from. On method I have been recently working with used the "<experimental/filesystem>" header file and the other uses "regex" to list the files. The "regex" method makes a nicer output and can limit what is displayed on the screen, but it will take some modification first.

IMHO I do not know what "din" and "dout" means to you, but for these streams I like to use "inFile" and "outFile". I have found that when reading through code it take less thought and work to understand what is being used. Just a thought. You can call your streams anything that you want.

Unless your compiler is pre2011 standards, from C++11 on the use of ".c_str()" is not needed. If you have to use ".c_str()" to open a file then you should consider upgrading the IDE/compiler or maybe you may be able to adjust the IDE to use the C++11 standards.

The if statement dealing with a file that did not open is OK, but again without listing the file names that can be used you could end up in an endless loop trying to find the correct file name. For an if statement like this I usually use:
1
2
3
4
5
6
if (!inFile)
{
	std::cout << "\n File \"" << filename << "\" did not open" << std::endl;

	return 1;  //exit(1);  // If not in "main".
}

Instead of getting th file name wrong a second time you leave the program until you have the correct file name.

whitenite1 wrote:
1
2
3
4
5
6
7
8
9
10
11
12
13
din >> fname[i]; // Why??

while (!din.eof())
{
din >> fname[i];
din >> paytype[i];
din >> rate[i];
din >> ytdGross[i];
i++; // Why increase i BEFORE assigning lname[i]??
// fname and lname won't match up anymore PLUS you'll be out-of-bounds in array
// after 10th name
din >> lname[i];
}


I can see why he is confused. On line 1 I believe yo meant to use "lname" instead of "fname". By inputting "fname" twice you will leave the first element of "lname" blank.

Usually a while loop with the while condition based on "eof" is the wrong way to read a file, but you have managed to use it correctly.

The more often method to read a file is:
1
2
3
4
5
6
7
8
9
10
11
12
while (din >> lname[i])
{
	din >> fname[i];
	din >> paytype[i];
	din >> rate[i];
	din >> ytdGross[i];

	// Or
	//din >> ytdGross[i++];

	i++;
}


I would suggest using "std::getline(din, lname, ',') and the same for "fname" because you may fine a first or last name that has a space in it and thet would through the whole read section off.

Your input file could end up looking something like this:

lname,fname,payType rate ytdGross


Now if "lname" or "fname" has a space in the name it will read correctly. After you read "ytdGross" you will need the line
din.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // <--- Requires header file <limits>. This will clear the input buffer before the next "std::getline" is used.

That is as far as I have tested so far.

Looking over the switch/case, cases "1" and "2" should call a function not contain the program. The idea of "main" and the case statements sre to direct the flow of the program not be the program. You have demonstrated that you can use functions. Make more use of them.

Also your for loops:for (int i = 0; i < 10; i++) would work better as: for (int i = 0; i < MAXSIZE; i++), but even that is wrong.

You assume that the input file will always have ten records, but it may not. It could have less than ten or more. This is where a "vector" is useful.

Another thing I noticed: if (paytype[i] == "S"). What is the value of "i" here? I found nowhere where you reset the value of "i" before you use it in the case statement. If you did input ten records then "i" would equal ten and this would put you trying to access the array past the last element boundary and this will not work. It will create a run time error.

You created a variable "numOfEmp", but never use it. When you read the file "numOfEmp" would be a better choice than "i". At this time the variable is never used, so I am not sure yet what to do with it.

Hope that helps,

Andy
Topic archived. No new replies allowed.