In my code below you will see at the bottom my very lame attempt at sorting the vector array of employee records by name, alphabetically. My friend tried to tell me how I'm supposed to do it, but I can't make any sense of it really, so if someone could just put it into context for me that would help me out tremendously. I'm almost done with this program, just need to do this and one other thing that should be no problem, so please and thank you very much.

Code:

#include <iostream>
#include <iomanip>
#include <fstream>
#include <vector>
#include <algorithm>
#include <cstdlib>
using namespace std;

class Records {
public:
    string name;
    int hours;
    double rate;
    int age;

    double pay;
    double tax;
    double net;
    /*double basepay;
     double tax;
     double netpay;*/

    double basepay(int hours, double rate){
        double pay, norm, over;
        if (hours>40)
        {
            //ot = hours-40;
            norm = 40*rate;
            over = (hours-40)*(rate*1.5);
            pay = norm+over;
        }
        else pay = hours*rate;
        return pay;
    }

    double taxpaid(int age, double pay){
        double percentage, tax;
        if (age >= 55) percentage = 0.50;
        else if (age < 55) percentage = 0.10;
        tax = pay * percentage;
        return tax;
    }

    double netpay(double pay, double tax){
        double net = pay - tax;
        return net;
    }
};

double Records::basepay(int,double);
double Records::taxpaid(int,double);
double Records::netpay(double,double);

int main() {

    cout << "\t\t\tMiser Corporation Payroll\n" << endl;

    ifstream datafile; // Declare input file
    datafile.open("datafile.txt"); // Open input file

    // Check for error opening input file
    if (!datafile)
    {
        cout << "Error opening file; program halted." << endl;
        exit(1);
    }

        Records employee;
    vector<Records> recordlist;

    employee.pay = 0;

    getline(datafile,employee.name);
    datafile >> employee.hours >> employee.rate >> employee.age;
    datafile.ignore();
    while (datafile) {
        cout << "Name: " << employee.name << endl;
        cout << "Hours worked: " << employee.hours << endl;
        cout << "Rate of pay: " << employee.rate << endl;
        cout << "Age: " << employee.age << endl;
        employee.pay = employee.basepay(employee.hours,employee.rate);
        cout << "Base pay: " << employee.pay << endl;
        employee.tax = employee.taxpaid(employee.age,employee.pay);
        cout << "Tax paid: " << employee.tax << endl;
        employee.net = employee.netpay(employee.pay,employee.tax);
        cout << "Net pay: " << employee.net << endl;
        cout << endl;
        recordlist.push_back(employee);
        getline(datafile,employee.name);
        datafile >> employee.hours >> employee.rate >> employee.age;
        datafile.ignore();
        employee.pay = 0;
    }

cout << endl;

    int oldest = 0;
    // Determine and print oldest employee(s):
    for (int i=0; i<recordlist.size(); i++) {
        if (recordlist[i].age > oldest){
            oldest = recordlist[i].age;
        }
    }
    cout << "Oldest employee(s): "
    << endl;
    for (int o=0; o<recordlist.size(); o++) {
        if (recordlist[o].age == oldest) {
            cout << " " << recordlist[o].name << "; " << recordlist[o].age << endl;
        }
    }
    cout << endl;

    // Determine and print youngest employee(s):
    int youngest = recordlist[0].age;
    for (int i=0; i<recordlist.size(); i++) {
        if (recordlist[i].age < youngest){
            youngest = recordlist[i].age;
        }
    }
    cout << "Youngest employee(s): "
    << endl;
    for (int y=0; y<recordlist.size(); y++) {
        if (recordlist[y].age == youngest) {
            cout << " " << recordlist[y].name << "; " << recordlist[y].age << endl;
        }
    }
    cout << endl;

    // Determine and print employee who paid the most in taxes:
    double hitax = 0; cout << "Employee who paid the most in taxes:" << endl;
    for (int i=0; i<recordlist.size(); i++)
        if (recordlist[i].tax > hitax) hitax = recordlist[i].tax;
    for (int i=0; i<recordlist.size(); i++)
        if (recordlist[i].tax == hitax) {
            cout.precision(2);
            cout << " " << recordlist[i].name << "; $";
            cout << fixed << recordlist[i].tax << endl;
        }

    // Print an alphabetically sorted list of all employees:
    sort (recordlist.begin(), recordlist.end());

    datafile.close(); // Close input file
    cout << "\n" << endl;
    cout << "The payroll program is complete.";
    return 0; // Close main program function
}

My friend's instructions:

If you want to use sort function to sort the vector you must define a less than function and pass it as the third parameter. It's very easy. Just create a new function that takes two employee objects by reference and returns a Bool. The whole function is one if else statement where you check whether the first parameter name is less than the second parameter name and return true or false accordingly. Then simply pass the name of the function to the sort function as if it was a variable -- don't put parentheses at the end of the name. It should be the last parameter passed. That's it.

Dani AI

Generated

As hinted, the missing piece is a comparator that tells std::sort how to order two Records. The expression a < b failed earlier because Records has no operator<; the comparator must compare the name strings inside the objects (and it should take const references to avoid copies).

A minimal, C++03-compatible comparator:

bool compareByName(const Records& a, const Records& b) {
    return a.name < b.name; // simple lexicographic, case-sensitive
}

// call
std::sort(recordlist.begin(), recordlist.end(), compareByName);

Alternatives and gotchas: a C++11 lambda can replace the free function; std::stable_sort preserves relative order for equal names; defining bool operator<(const Records& rhs) const { return name < rhs.name; } inside Records lets std::sort be called without a third argument. The comparator must implement a strict weak ordering (the simple return a.name < b.name; does).

If names should be compared case-insensitively, convert both sides to lower-case (or use a locale-aware comparison) before comparing. Example helper (brief):

std::string lower_copy(std::string s) {
    std::transform(s.begin(), s.end(), s.begin(), ::tolower);
    return s;
}
bool ciCompare(const Records& a, const Records& b) {
    return lower_copy(a.name) < lower_copy(b.name);
}

Finally, note that sorting alone does not print results: after the sort call iterate recordlist and output name (and any other fields) so the sorted order is visible. This addresses the two things missing from ’s program: a proper comparator and printing the sorted list.

Recommended Answers

All 3 Replies

Your friend is correct. Carefully read his instructions.

create a function that takes two employee objects by reference and returns a bool

bool lessThan( Records& a, Records& b );

function is one if else statement where you check whether the first parameter name is less than the second parameter name and return true or false accordingly

bool lessThan( Records& a, Records& b
 {
   // implement the alphabetic check here!
   if( aisbeforeb )
   {
   return true;
   }
   return false;

. Then simply pass the name of the function to the sort function as if it was a variable

sort (recordlist.begin(), recordlist.end(), lessThan );

What do you mean, implement the alphabetic check here? What alphabetic check? What do I do with "aisbeforeb"??? I tried a < b, but that didn't work, which I assumed. So....

Just show me how to implement this in my code because I have no idea what any of that is I never learned it. I need to see it in action I don't get it at all I know I'm missing something real fundamental in the big picture.

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.