I have this function which reads in a workers.age from a structure. It determines how much taxes that worker will have to pay based on a base salary that is also passed to that function.

I am able to print out the net salary and amount of taxes paid for each person. What I need to do now is sort that list according to the net pay and display in descending order the net salary and worker name.

I have tried inserting a bubble sort into this function but cannot get this to work. How can I place a sort into this function? Or must I use another function?

Thank you.


void tax_paid (person worker[], double base[], const int emps)  //7.Takes in age, base pay and amnt of employees.
{                                                        
 double t=0;
 double tax = 0;
 double mosttax = 0;
 double net=0;
 int index;     //Variable for tax rate.
 bool swap;

 for (int i=0;i<emps;i++)
 {
   if (worker[i].age >= 55)        //Determines tax rate based on age.
   {
    tax = (base[i] * .50);         
    net = base[i]-tax;             //Assigns net pay to "net"
    cout << worker[i].lname << " "  << left << setw(10)<< worker[i].fname <<   " Earned after taxes: $" << net << " Tax rate: $" << tax << "\n"; 
   } 
    else
    {
    tax = (base[i] * .10);
    net = base[i]-tax;
    cout  << worker[i].lname << " " << left << setw(10)<< worker[i].fname << " Earned after taxes: $" << net << " Tax rate: $" << tax << "\n"; //Displays Total paid taxes and tax amount.
    }
    
    if (tax > mosttax)            
      {                           //Determines employee who paid most in taxes.
      mosttax=tax;
      index=i;    
      }       
 }
//Displays name and taxes paid to employee who paid most in taxes.
cout << "\n";
cout << worker[index].lname << " " << worker[index].fname << " Paid the most in taxes: $" << mosttax << "  \n";
cout << "\n";
}

What was the code that you were using for the bubble sort, and where did you place it?

You're either calculating tax, printing a list, or sorting, but not all three at the same time. They are three distinct tasks and should be handled as such. Combine them at your own peril.

Aside from that, I see no attempt at a bubble sort anywhere, so I have no idea where that went wrong.

At minimum, a bubble sort needs...

  1. Rules on how to calculate whether an object is less than another object.
  2. A swap method.

If you are trying to compare two objects and that comparison is based on the net pay, you need to store the net pay. You do not. You have a local variable called "net" that is not part of your struct (or if it is, you are not using it). You can't compare TWO objects' pay because you only have storage for ONE object's net pay. So "net" needs to be part of your struct. You need to STORE it, not just print it.

What was the code that you were using for the bubble sort, and where did you place it?

I actually removed it, because it seemed like there was too much going on in that function. I had it at line 24 and then I tried it at line 30.

Vernon, can I store net salary in net[] and return that to the Main()? Then create a sort function that uses net[]? Also by two objects do you mean the two IF statements? I'm not sure how else to store that info other than using 2 different variables. But if I do that I cannot sort them using this kind of sort, correct?


The type of sort I was using was:

do
   {
     swap = false;
     for (int i=0;i<emps;i++)
     {
         for (int j=i+1;j<emps;j++)
       {
          if (array[i] > array[j])
           {
             temp=array[i];
             array[i]=array[j];
             array[j]=temp;
           }
       }
     }
while (swap);

>> Vernon, can I store net salary in net[] and return that to the Main()? Then create a sort function that uses net[]?

You could, but you shouldn't.


>> Also by two objects do you mean the two IF statements?

No, I mean two persons.


>> I'm not sure how else to store that info other than using 2 different variables.

Stick tax and net in your person struct (and possibly even base)...

struct person
{
    char lname[8];
    char fname[8];
    double age;
    double tax;
    double net;
}

Get rid of lines 4 and 6 in your original code. Change any line with "tax" or "net" to worker.tax and worker.net.

After you fill those in for everybody, then you can sort using your bubble sort.

I've moved tax and net and base into my function and it makes for a nicer looking and easier to manipulate program.

The only issue I cannot seem to get around is that I would like to print the first and last name along with the sorted net pay. The pay sorts perfectly now, but it is also sorting the names in alphabetical order. I cannot seem to separate the two. In other words I want to print to the screen the net pay sorted along side its corresponding name. But it is sorting both fields, rather than just 1(worker.net)


void net_paid (person worker[], const int emps)  //7.Takes in age, base pay and amnt of employees.
{                                                        

 double temp;
 bool swap;  
 
   do
     {
      swap = false;
      for(int i=0;i<emps;i++)
      {
       for(int j=i+1;j<emps;j++)
       {
        if(worker[i].net < worker[j].net)
        {
         temp = worker[i].net;
         worker[i].net = worker[j].net;
         worker[j].net = temp;               
        }    
       }
       cout << worker[i].lname << " "<< worker[i].fname << ": $" << worker[i].net <<"\n";
      }
     }
     while (swap);
}

Remember when I mentioned that displaying and sorting are two separate tasks; combine them at your peril? Before you even consider worrying about a bad sort, separate the two. Print them before, sort them, then print them after. Make sure everything is as it is supposed to be. And consider renaming this function and re-commenting so that the name/comments accurately reflect what it does.

void sort_workers (person worker[], const int emps)
{                                                        
  // code to print out ALL employees


 double temp;
 bool swap;  
 
   do
     {
      swap = false;
      for(int i=0;i<emps;i++)
      {
       for(int j=i+1;j<emps;j++)
       {
        if(worker[i].net < worker[j].net)
        {
         temp = worker[i].net;
         worker[i].net = worker[j].net;
         worker[j].net = temp;               
        }    
       }
       /* get rid of this line! No cout displays allowed inside of the sort! The only exception to this rule is debugging statements that are to be taken out once everything works */ //cout << worker[i].lname << " "<< worker[i].fname << ": $" << worker[i].net <<"\n";
      }
     }
     while (swap);

  // code to print out ALL employees.  Just copy and paste the code you used before the sort
}

Is the sort correct? I don't know. I haven't looked at it. This is how you find out for sure. Make sure the pre-sorted data is correct. Make sure the post-sorted data is correct. Worry about bugs in the sort if and only if the pre-sorted data is correct and the post-sorted is not.

If the sort is in fact incorrect, there can be several problems...

  1. Bad comparison.
  2. Bad swap.
  3. Something else.

The swap is definitely working. I checked and it is sorting properly. What I realized is that the values for .lname and .fname are still in alphabetical order from when I sorted them in a previous function. If I move the call to my net_paid function before the call to my name sort function, it works perfectly.

It seems that my name sort function permanently alphabetized the order of .lname. Is this normal behavior?

Here is my main() code:

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

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

using namespace std;
void tax_paid (person worker[], const int emps);
void oldest (person worker[], const int emps);
void sort(person worker[], const int emps);
void net_paid (person worker[], const int emps); 

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

cout << "Miser Corporation Payroll \n\n";   //1. Heading.

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;
    }           
   while (!datafile.eof())       //5. Detecting end of file. events in {} occur until end of file reached.
   {            
    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)
          {
            overtime = (emp[i].hours - 40) * (emp[i].pay_rate * 1.5);  //Calculates overtime only
            emp[i].base = overtime + (emp[i].pay_rate * 40);              //overtime + salary
            cout << "Base Pay: $" << emp[i].base << "\n\n";             
          }
            else                  //3. Displays base pay w/o overtime
            {
            emp[i].base =  emp[i].hours * emp[i].pay_rate;   
            cout << "Base Pay: $" << emp[i].base << "\n\n";    
            }     
         
        }
    }
tax_paid(emp,num_emps);            //4-5,7. Call to function to determine taxes paid
oldest(emp, num_emps);             //6. Call to function for oldest and youngest employee
net_paid(emp, num_emps);           //9. Sorts the net pay of all employees.

//Prints the name and net pay of all employees sorted by net pay. 
for (int i=0;i<num_emps;i++)
{
    cout << emp[i].lname << " " << emp[i].fname << " $" << emp[i].net << "\n";
}

sort(emp, num_emps);  //Alphabetically sorts the employees by last name. 


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

}

The swap is definitely working. I checked and it is sorting properly.

What I realized is that the values for .lname and .fname are still in alphabetical order from when I sorted them in a previous function. If I move the call to my net_paid function before the call to my name sort function, it works perfectly.

It needs to work perfectly no matter what order you do it. Quite possibly it's "working" due to plain old dumb luck. I don't know.

It seems that my name sort function permanently alphabetized the order of .lname. Is this normal behavior?

No. Sounds like either one of your swaps is wrong or one of your sorts is wrong. There's nothing "permanent" about a sort. The next sort undoes the last sort.

So what doesn't work? Clearly you are getting some bad results somewhere, but it's not clear where.


Note. This is a "bad" sort in that it has an outer do-while loop that will execute exactly once. Hence it's not a "loop".

do
   {
     swap = false;
     for (int i=0;i<emps;i++)
     {
         for (int j=i+1;j<emps;j++)
       {
          if (array[i] > array[j])
           {
             temp=array[i];
             array[i]=array[j];
             array[j]=temp;
           }
       }
     }
while (swap);

It's the same as this...

for (int i=0;i<emps;i++)
     {
         for (int j=i+1;j<emps;j++)
       {
          if (array[i] > array[j])
           {
             temp=array[i];
             array[i]=array[j];
             array[j]=temp;
           }
       }
     }

The "swap" variable is never set to true, so the while condition will always be false, so I deleted everything dealing with the "swap" variable. It's also not a bubble sort. Bubble sorts only compare adjacent objects. That doesn't mean that the items are not sorting correctly the way you had it.

The swap variable has me a little confused, but I removed also from my "name sort" function and it still sorts properly.

I am at a loss with this one. From my inexperienced eyes both sorts look right. They work perfectly on their own. Below is the other sort which sorts the names. As soon as I move the calling of this sort to the first one in Main(), it sorts .lname in alphabetical order, for the rest of the program. If I move it to the bottom of the list of called functions, everything works fine and it only sorts whats in that function.

void name_sort(person worker[], const int emps) //Alphabetizes first and last name.
{
  char temp[8];
  char tempf[8];

  cout << "\n";
  cout << "Miser Corporation employees in alphabetical order: \n\n";
   
     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
     }
}

The swap is incorrect and the comparison is incorrect. You always swap an entire record. You don't swap names and leave the data. Think about it. Two records.

record 0

lname = "Frasier"
fname = "Bob"
hour = 4.5


record 1

lname = "Johnson"
fname = "Alan"
hour = 3.5

First off, which record is "less than" the other record? "Frasier" is less than "Johnson", but "Alan" is less than "Bob".

Now look at line 14. i is 0, j is 1. "Frasier" is less than "Johnson", so line 14 is going to evaluate to false. No swap.

Now look at line 20. "Bob" is greater than "Alan", so lines 21 to 23 execute. So we end up with...

record 0

lname = "Frasier"
fname = "Alan"
hour = 4.5


record 1

lname = "Johnson"
fname = "Bob"
hour = 3.5

So we have two employees and we've discombobulated their names. "Alan Frasier" and "Bob Johnson", neither of whom exist. We could try to figure out who is supposed to have 3.5 hours and who is supposed to have 4.5 hours, but it's already broken beyond repair. Has this error not shown up yet?

When you compare, you compare ONE thing. One record is either less than another record or it is not, so figure out which comes first: "Alan Johnson" or "Bob Frasier". Then if you swap, you swap the entire record, not just part of it.

I got it!! Makes perfect sense.

Compare one thing, worker.net, then swap the entire struct, worker. Keeps it all together. now it works no matter where it is positioned when I call it in Main().

Thank you!


void net_paid (person worker[], const int emps)  //7.Takes in age, base pay and amnt of workerloyees.
{                                                        
 int index=0;
 person temp;   //Completely forgot to set temp to the struct.
 
        
      for(int i=0;i<emps;i++)
      {
       for(int j=i+1;j<emps;j++)
       {
        if(worker[i].net < worker[j].net)  //Compare one thing.
        {
         temp = worker[i];                 //Swap entire struct.
         worker[i] = worker[j];
         worker[j] = temp;               
        }    
       }
     
      }
}
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.