I have a data file which includes an employee name, hours worked, salary and age.

I have to manipulate this data:

Print out the data as it is read in.
Compute overtime(over 40 hours)
Compute tax paid per employee using a specific formula.
Sort the list by name.
And a few others.

I figure the best way to do this is using a structure:

struct person
{
       char name[20];
       int hours;
       int age;
       double pay; 
       };

Is this the most effective way to approach this?

Also I really am not sure how to fill the structure with the data from the file.

Data File:

Duck, Donald 45 3.50 60
Mouse, Mickey 35 6.50 55
Brown, Charlie 35 3.00 20
Oyle, Olive 40 4.50 60
Man, He 45 7.50 20
Ra, She 40 3.50 20
Jetson, George 45 3.50 55
Starr, Brenda 35 8.40 60
Woman, Wonder 40 3.50 55
Jets, Green 45 13.50 55
Barr, Jimmy 35 9.00 60
Evans, Robert 40 8.00 55

Thank you for your help in advance.

Line 3 - char name[20]; Perfectly acceptable, but you're using C++, so if there is not a reason not to, take advantage of the string class.

string name;

You might perhaps want to keep track of last and first name since that is how the file is organized.

string lastName;
string firstName;

That's possibly 6 of one, a half dozen of the other. There's no right or wrong here. Just pick one of them.

The struct you have seems reasonable to me.

Actually, line 6. "pay". is this the "pay rate" or the "pay"? if it's the pay rate, you may want to rename it to payRatePerHour or something to make it clear.

To fill the data make a loop or a function that takes the struct as input and then sets each person.name..person.pay ect...

If your using a file look how to take everything up til the comma, then up till the next space ect...

I have named the file "datafile".

This is a rough code. Am I on the right track?

for (i = 0; i < num_emps; i++)                        
        {                                                     
        for (int j = 0; j < 4; j++)
        datafile >> emp[i].name, emp[i].hours, emp[i].age, emp[i].pay_rate;   
        }

>> Am I on the right track?

No. The inner for-loop makes no sense. Get rid of it. You don't even use the j variable.

As for line 4, you need to replace the commas with >>

If you do that, you'll get this...

datafile >> emp[i].name >> emp[i].hours >> emp[i].age >> emp[i].pay_rate;

That's better, but still not right. I'm not sure which comes first in the file, hours or age, but pay_rate does not come last, so that's wrong.

In addition, reading in the name is a little more complicated. You have the last name, then a comm, then a space, then the first name, so you can't just read it all in with one >> statement.

That makes more sense. I have split up the first and last name, I see your point with that. I am getting some crazy random numbers on my output though. Almost seems like the struct elements need to be set to zero. Not sure how to do that within a struct, but I will research that.

Isn't the second for loop necessary for a 2D array? Just asking. I have included all of my code, in case there is something else I missed.

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

struct person  //Employees name, hours worked, age and payrate
{
       char lname[8];
       char fname[8];
       int hours;
       int age;
       double pay_rate; 
       };

using namespace std;

int main()
{
const int num_emps = 12; //num of employees
person emp[unm_emps];  //var created from structure




fstream datafile;                                   //Naming and opening data file
    datafile.open("hw3.txt");
    if(!datafile)
    {
      cout << "Could not open file. \n\n";          //Verifies file exists.
    cin.get();
    cin.get();
    
    return 0;
    }           
                 
    for (int i = 0; i < num_emps; i++)    //Data being copied from the file to an array
        {                                                     
        datafile >> emp[i].lname >> emp[i].fname >> emp[i].hours >> emp[i].age >> emp[i].pay_rate;   
        cout << emp[i].fname << " \n" << emp[i].hours << " \n" << emp[i].age << " \n" << emp[i].pay_rate << " \n"; 
        }


cin.get();
cin.get();


}

>> Isn't the second for loop necessary for a 2D array?

You don't have a 2D array. You have a 1D array. I assume "unm" is a typo and should be "num".

person emp[unm_emps];  //var created from structure

I reiterate my last point regarding the order you are reading things in and the order in the file. Make sure they match.

Duck, Donald 45 3.50 60
datafile >> emp[i].lname >> emp[i].fname >> emp[i].hours >> emp[i].age >> emp[i].pay_rate;

Good catch on the order and misspelling. I guess I need to slow down a little.
I also changed the "hours" var from int to double in the structure and I managed to get it to work and print all values! Excellent!

Thank you for the quick responses!

Now onto the calculations...

What I am trying to do here is calculate a tax rate and print out the total salary plus taxes using a function. I am having trouble passing the structure to the function.

Error says Absolute binding at "i"

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

struct person  //Employees name, hours worked, age and payrate
{
       char lname[8];
       char fname[8];
       double hours;
       int age;
       double pay_rate; 
       };

using namespace std;
void tax_paid (double age, double base, const int emps);


int main()
{
const int num_emps = 12; //num of employees
person emp[num_emps];  //var created from structure
double base_pay = 0;
double overtime = 0;


fstream datafile;                                   //Naming and opening data file
    datafile.open("hw3.txt");
    if(!datafile)
    {
      cout << "Could not open file. \n\n";          //Verifies file exists.
    cin.get();
    cin.get();
    
    return 0;
    }           
                 
    for (int i = 0; i < num_emps; i++)    //Data being copied from the file to an array
        {                                                     
        datafile >> emp[i].lname >> emp[i].fname >> emp[i].hours >> emp[i].pay_rate >> emp[i].age;   
        cout << emp[i].lname << " " << emp[i].fname << " \n" << emp[i].hours << " Hours \n" << "$" << emp[i].pay_rate << " per hour \n" << "Age: " << emp[i].age << " \n"; 
        if (emp[i].hours > 40)
          {
            overtime = (emp[i].hours - 40) * (emp[i].pay_rate * 1.5);  //Calculates overtime only
            base_pay = overtime + (emp[i].pay_rate * 40);              //overtime + salary
            cout << "Base Pay: $" << base_pay << "\n\n";             
          }
            else                  //Displays base pay w/o overtime
            {
            base_pay =  emp[i].hours * emp[i].pay_rate;   
            cout << "Base Pay: $" << base_pay << "\n\n";    
            }     
         
        }

tax_paid(emp.hours, base_pay, num_emps); //Call to function to determine taxes paid


cin.get();
cin.get();
return 0;

}

void tax_paid (double age, double base, const int emps)  //Takes in age, base pay and amnt of employees.
{                                                        
 double tax = 0;     //Var for tax rate

 for (int i=0;i<emps;i++)
 {
   if (age >= 55)        //Determines tax rate based on age.
   {
    tax = (base* .50) + base;
   } 
    else
    {
    tax = (base * .10) + base;
    cout << "After Taxes: " << tax << "Tax rate: " << base * .10; //Displays Total paid taxes and tax amount.
    }
 }
}

I was able to figure it out!! I made some corrections to my function and did a little trial and error on calling it. Here is my function:

void tax_paid (person worker[], double base[], const int emps)  //Takes in age, base pay and amnt of employees.
{                                                        
 double tax = 0;     //Var for tax rate

 for (int i=0;i<emps;i++)
 {
   if (worker[i].age >= 55)        //Determines tax rate based on age.
   {
    tax = (base[i] * .50) + base[i];
    cout << worker[i].lname << " " << worker[i].fname << " After Taxes: " << tax << "Tax rate: " << base[i] * .50 << "\n"; 
   } 
    else
    {
    tax = (base[i] * .10) + base[i];
    cout << worker[i].lname << " " << worker[i].fname << " After Taxes: " << tax << "Tax rate: " << base[i] * .10 << "\n"; //Displays Total paid taxes and tax amount.
    }
 }
}

The call:

tax_paid(emp, base_pay, num_emps); //Call to function to determine taxes paid

On to the next step!

Why do you have an array for base pay aswell? If the base pay is different for each person, why not just make base_pay another member variable for the struct?

I thought about that. Maybe I will tackle that before the final draft.

Would you be able to help me with this sort?

I am trying to sort the names in Alphabetical order. My output is in random order.

Any reason why that would occur from my code?:

void sort(person worker[], const int emps) 
{
  char temp[8];
  bool swap;
  
   do
   {
     swap = false;
     for (int i = 0; i < emps; i++)
     {
         if (worker[i].fname > worker[i + 1].fname)
         {
              strcpy(temp,worker[i].fname);
              strcpy(worker[i].fname,worker[i+1].fname);
              strcpy(worker[i+1].fname,temp); 
         }
     cout << worker[i].fname <<"\n";
     }
    
   }
   while (swap);
   
}

You can't use < and > by themselves to compare the strings. Use the strcmp function.

Ok. So I decided to replace my char with string.

I am now getting "string does not name a type" in the function. I have tried both <string> and <cstring> headers to no avail. Am I missing something?

#include <iostream>
#include <fstream>
#include <iomanip>
#include <cstring>

struct person  //Employees name, hours worked, age and payrate
{
       string lname[8];
       string fname[8];
       double hours;
       int age;
       double pay_rate; 
       };

Also is my sort function correct? I was not getting a sorted output from it. Just a copy of the current order.

void sort(person worker[], const int emps) 
{
  string temp[8];
  bool swap;
  
   do
   {
     swap = false;
     for (int i = 0; i < emps; i++)
     {
         if (worker[i].lname > worker[i + 1].lname)
         {
              strcmp(temp,worker[i].lname);
              strcmp(worker[i].lname,worker[i+1].lname);
              strcmp(worker[i+1].lname,temp); 
         }
      cout << worker[i].lname <<"\n";
     }
   }
   while (swap);
   
}

Thanks

Ok. So I decided to replace my char with string.

I am now getting "string does not name a type" in the function. I have tried both <string> and <cstring> headers to no avail. Am I missing something?

#include <iostream>
#include <fstream>
#include <iomanip>
#include <cstring>

struct person  //Employees name, hours worked, age and payrate
{
       string lname[8];
       string fname[8];
       double hours;
       int age;
       double pay_rate; 
       };

Also is my sort function correct? I was not getting a sorted output from it. Just a copy of the current order.

void sort(person worker[], const int emps) 
{
  string temp[8];
  bool swap;
  
   do
   {
     swap = false;
     for (int i = 0; i < emps; i++)
     {
         if (worker[i].lname > worker[i + 1].lname)
         {
              strcmp(temp,worker[i].lname);
              strcmp(worker[i].lname,worker[i+1].lname);
              strcmp(worker[i+1].lname,temp); 
         }
      cout << worker[i].lname <<"\n";
     }
   }
   while (swap);
   
}

Thanks

The C++ string class is called std::string, you can find it in the <string> header.
AFAIK, cstring is used when creating MFC programs.

So, change the <cstring> to <string> and you can then either declare that you are using namespace std; or you can use the scope operator when declaring your string variables (or anything from the std namespace).

e.g.

#include <iostream>
    #include <fstream>
    #include <iomanip>
    #include <string>//change to this
     
   using namespace std; //declare this to use the "whole" std namespace
//OR you can use the :: operator as follows(which is preferred)

    struct person //Employees name, hours worked, age and payrate
    {
    std::string lname[8];
    std::string fname[8];//if you are using the :: operator, you DON'T need to include the using namespace line
    double hours;
    int age;
    double pay_rate;
    };

I have made those changes, but now I get an error "no match for >> operator in data file" at line 3.

for (int i = 0; i < num_emps; i++)    //2. Data being copied from the file to an array
        {                                                     
        datafile >> emp[i].lname >> emp[i].fname >> emp[i].hours >> emp[i].pay_rate >> emp[i].age;   
        cout << emp[i].lname << " " << emp[i].fname << " \n" << emp[i].hours << " Hours \n" << "$" << emp[i].pay_rate << " per hour \n" << "Age: " << emp[i].age << " \n"; 
        if (emp[i].hours > 40)
          {

I have made those changes, but now I get an error "no match for >> operator in data file" at line 3.

for (int i = 0; i < num_emps; i++)    //2. Data being copied from the file to an array
        {                                                     
        datafile >> emp[i].lname >> emp[i].fname >> emp[i].hours >> emp[i].pay_rate >> emp[i].age;   
        cout << emp[i].lname << " " << emp[i].fname << " \n" << emp[i].hours << " Hours \n" << "$" << emp[i].pay_rate << " per hour \n" << "Age: " << emp[i].age << " \n"; 
        if (emp[i].hours > 40)
          {

emp is an array of persons, which means each cell in the array should hold a person which has a lname,fname,hours and payrate. It doesn't mean that each cell should have a fname,lname,hours and payrate.
i.e.

Person employee;
datafile>>employee.lname>>employee.fname>>employee.hours>>employee.pay_rate>>employee.age;
emp[i] = employee;

Hopefully I am not talking out of my backside

I would do binary output to file, then I would invent sorting function

When you use string, you don't specify a length...

struct person //Employees name, hours worked, age and payrate
    {
    std::string lname;
    std::string fname;//if you are using the :: operator, you DON'T need to include the using namespace line
    double hours;
    int age;
    double pay_rate;
    };

When you use character arrays, you specify a length...

struct person //Employees name, hours worked, age and payrate
    {
    char lname[8];
    char fname[8];
    double hours;
    int age;
    double pay_rate;
    };

Ahh ok. No legnth for strings.

I have decided to stick with char. string was giving me way too many errors and it's getting late so I will keep this program with char's and use strings on my next one. Here is my final bubble sort to alphabetically sort the list of employees by last name. Thank you all for your advice.

void sort(person worker[], const int emps) 
{
  int index = 0;
  char temp[8];
  char tempf[8];
  bool swap;
  
  cout << "Miser Corporation employees in alphabetical order: \n\n";
   do
   {
     swap = false;
     for (int i=0;i<emps;i++)
     {
         for (int j=i+1;j<emps;j++)
       {
         if (strcmp(worker[i].lname,worker[j].lname)>0) //Sorting Last Name of employee
         {
              strcpy(temp,worker[i].lname);
              strcpy(worker[i].lname,worker[j].lname);
              strcpy(worker[j].lname,temp); 
         }
         if (strcmp(worker[i].fname,worker[j].fname)>0) //Matching First name with sorted last name
         {
              strcpy(tempf,worker[i].fname);
              strcpy(worker[i].fname,worker[j].fname);
              strcpy(worker[j].fname,tempf);                                           
         }
       }
      cout << worker[i].lname << " " << worker[i].fname << "\n"; //Printing out first and last name sorted by last
     }
     
   }
   while (swap);
   
}
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.