Click here to Skip to main content
15,887,175 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I have successfully populated linked list with data from a text file. Linked list contains structure that has 5 fields of type string.

I wish to sort the list by a certain structure field ( ascending or descending ). I have decided to overload operator < but I do not know how to implement it.

So far I am able to sort list by one fixed field. Here is the relevant code:
C++
#include <iostream>       
#include <list>           // std::list
#include <fstream>        // std::ifstream, std::ofstream
#include <string>         // std::string
#include <algorithm>      // std::remove, std::remove_if
#include <sstream>        // std::istringstream

class Lista
{
private:
    struct Person
    {
        // data from file
        std::string lastName;  // other fields omitted for keeping brevity

        // operator < ( needed for correctly sorting the linked list )
        bool operator< ( const Person &p )const
        {
            return lastName > p.lastName;
        }

        // constructor / destructor ... omitted for keeping brevity 
    };

    // linked list that holds all the data from files
    std::list<Person> persons;

public:

// constructor / destructor ... omitted for keeping brevity

// method for sorting the list
    void sortList()
    {
        persons.sort();
    }
};


I would like to add enum of choices, so I can use only one overloaded operator < for sorting.

Something like this:

C++
class Lista
{
private:
    struct Person
    {
        //================ here I could add enum of choices ============//

        enum choice { FIELD1, LASTNAME, FIELD2 }; // you get the point
        bool ascending;  // decides if it is ascending or descending

        //==============================================================//

        // data from file
        std::string lastName;  // other fields omitted for keeping brevity

        // operator < ( needed for correctly sorting the linked list )
        bool operator< ( const Person &p )const
        {
            if ( choice == FIELD1 )  
                return field1 < p.field1;

            if ( choice == FIELD2 )  
                return field2 < p.field2;

            if ( choice == LASTNAME )  
                 return lastName > p.lastName;
        }

        // constructor / destructor ... omitted for keeping brevity 
    };

    // linked list that holds all the data from files
    std::list<Person> persons;

public:

// constructor / destructor ... omitted for keeping brevity

// method for sorting the list
    void sortList( Person::choice ch, bool ascending)
    {
        // here I should use the parameters to invoke proper sorting 
        persons.sort();
    }


I really have no idea how to do this, can you please help me?
Posted
Updated 24-May-14 4:59am
v2

1 solution

I wouldn't choose the different path inside the sort function. I would use instead different comparators. For instance, have a look at the following code:
C++
#include <list>
#include <string>
#include <iostream>
using namespace std;

struct my_struct
{
  my_struct(int i, string s):i(i),s(s){}
  int i;
  string s;
};

struct CBIA
{
  bool operator()(const my_struct & m1, const my_struct & m2){ return m1.i<m2.i; }
};

struct CBID
{
  bool operator()(const my_struct & m1, const my_struct & m2){ return m1.i>m2.i; }
};

struct CBSA
{
  bool operator()(const my_struct & m1, const my_struct & m2){ return m1.s<m2.s; }
};
struct CBSD
{
  bool operator()(const my_struct & m1, const my_struct & m2){ return m1.s>m2.s; }
};


int main()
{
  list < my_struct> l;

  l.push_back( my_struct(5, string("alpha")));
  l.push_back( my_struct(1, string("gamma")));
  l.push_back( my_struct(20, string("delta")));
  l.push_back( my_struct(-100, string("beta")));

  for (;;)
  {
    int i;
    cout << "sort: " << endl << " 0 by int asc" << endl << " 1 by int desc" << endl << " 2 by string asc" << endl << " 3 by string desc" << endl << " -1 quit" << endl;
    cin >> i;
    if (i == -1) break;

    switch(i%4)
    {
    case 0:
      l.sort(CBIA());
      break;
    case 1:
      l.sort(CBID());
      break;
    case 2:
      l.sort(CBSA());
      break;
    case 3:
      l.sort(CBSD());
      break;
    }

    for (list<my_struct>::iterator it = l.begin(); it != l.end(); ++it)
    {
      cout << "{" << it->i << "," << it->s << "}" << endl;
    }
  }
}
 
Share this answer
 
Comments
Maciej Los 24-May-14 12:15pm    
+5!
AlwaysLearningNewStuff 24-May-14 14:45pm    
Thank you, it works!

Is there a way to add bool variable to the functors CBSA, CBSD... so I can write in their body something like this:

struct CBSD
{
bool operator()(const my_struct & m1, const my_struct & m2, bool ascending )
{
asc ? return m1.s < m2.s : return m1.s > m2.s;
}
};


If this is possible, how should I change l.sort(CBSD()); to properly call functor?

Thank you so much, I have 5ed it!
Stefan_Lang 26-May-14 7:53am    
You could add that flag as a member of the struct and either set it beforehand, or add a constructor that takes it as a parameter:
struct CBSD {
bool asc_;
CBSD(bool asc) : asc_(asc) {}
bool operator()(const my_struct & m1, const my_struct & m2 )
{
asc_ ? return m1.s < m2.s : return m1.s > m2.s;
}
};

...

l.sort(SBSD(true));
AlwaysLearningNewStuff 26-May-14 11:05am    
Thank you! I missed that part in code examples I have studied... Best regards.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900