Dr. Ann Huxtable said:
I am reading a CSV (comma seperated value) file into a 2D array. I want
to be able to sort multiple columns (ala Excel), so I know for starters,
I cant be using the array, I need something more sophistictated like a
vector of row objects.
Yes, a vector of struct or class objects that represent rows, would be
more appropriate for this.
2). Sort the data by specified columns (say column 2, and 4)
You need to supply a custom comparison function to the standard sort()
function. Here's an example that I gave my students last year. Each
comparison function sorts by one field (column) only; to sort by more than
one field together, expand the comparison logic in the
function accordingly.
// profsort.cpp
//
// Demonstrates how to sort a vector of classes by supplying (a) a
// comparision function or (b) a comparison function object to the
// standard sort() function.
//----------------------------------------------------------------------
#include <iostream>
#include <fstream>
#include <iomanip>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
//---------------------------------------------------------------------
// a simple class for storing data about professors
class Professor
{
public:
Professor (const string& initFN, const string& initLN,
const string& initOffice);
void Display() const;
friend int CompareByLastName (const Professor& lhs,
const Professor& rhs);
friend class CompareByOffice;
private:
string lastName, firstName, office;
};
// Constructor
Professor:
rofessor (const string& initFN, const string& initLN,
const string& initOffice)
: lastName(initLN), firstName(initFN), office(initOffice) {}
// A simple one-line display
void Professor:
isplay() const
{
cout << setw (15) << lastName
<< setw (10) << firstName
<< setw (20) << office
<< '\n';
}
// Comparison function for sorting by last name; it needs to
// be a friend function so it can access private data of the class
int CompareByLastName (const Professor& lhs, const Professor& rhs)
{
return (lhs.lastName < rhs.lastName);
}
// Here's another way to set up the comparison: a function object.
// This one compares by office location. This class needs to be
// a friend class of Professor so it can use private data.
class CompareByOffice
{
public:
int operator () (const Professor& lhs, const Professor& rhs)
{ return (lhs.office < rhs.office); };
};
//----------------------------------------------------------------------
void DisplayVector (const vector<Professor>& profs)
{
cout << '\n';
for (int k = 0; k < profs.size(); ++k)
{
profs[k].Display();
}
}
//----------------------------------------------------------------------
//----------------------------------------------------------------------
int main ()
{
ifstream profsfile ("profs.dat");
vector<Professor> profs;
// File format is one professor per line, with the fields separated
// by tabs
string firstName, lastName, office;
while (getline (profsfile, firstName, '\t')
&& getline (profsfile, lastName, '\t')
&& getline (profsfile, office, '\n'))
{
profs.push_back (Professor (firstName, lastName, office));
}
profsfile.close ();
cout << "\nBefore sorting:\n";
DisplayVector (profs);
// sort by last name, using an ordinary function for the comparison
sort (profs.begin(), profs.end(), CompareByLastName);
cout << "\nAfter sorting by last name:\n";
DisplayVector (profs);
// sort by office location, using a function object for the comparison
sort (profs.begin(), profs.end(), CompareByOffice());
cout << "\nAfter sorting by office:\n";
DisplayVector (profs);
cout << '\n';
return 0;
}