2

This might be somewhat of a noob question but here's my problem; I have a class Card with two different int values, looks like this.

#pragma once
class Card
{
public:
int value;
int suite;

Card(int v, int s);
~Card(void);

void printCard();
int getScore();
};

Now I want to sort 5 cards specifically by their value. I tried putting them into a vector and then using std::sort but I couldn't get it to work. So my question is what's the best way to do this?

Gilles Quénot
  • 173,512
  • 41
  • 224
  • 223

3 Answers3

3

You will need to overload the operator<:

bool operator<(const Card& lhs, const Card& rhs){
.... logic here ... 
}

And then use std::sort. You may need to make this operator friend for your class. Alternatively in the class definition you may implement:

class Card {
 ....
 public:
  bool operator<(const Card& other) const {
  .... logic here...
  }
}; // end of class Card
Ivaylo Strandjev
  • 69,226
  • 18
  • 123
  • 176
2

You have two options for using std::sort. One is to overload operator < for your class:

bool operator< (const Card &lhs, const Card &rhs) {
  return lhs.value < rhs.value;
}

However, only do this if it really makes sense to always compare Card objects like this. If you only need this for a particular sorting, you can use the version of sort which accepts a custom comparator.

There are multiple ways to define the predicate. For reusable, but simple criteria, a static function in the class can be used:

class Card
{
public:
  // ... as before
  static bool lesserValue(const Card &lhs, const Card &rhs) {
    return lhs.value < rhs.value;
  }
};

Usage:

std::sort(from, to, &Card::lesserValue);

For a one-shot thing (or for complex criteria which need to preserve internal state), use a class derived from std::binary_function and implement the comaprison logic in its operator(). In C++11, you can also use lambda functions for this:

std::sort(from, to, [](const Card &lhs, const Card &rhs) { return lhs.value < rhs.value; });
Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455
  • Very much appreciated, and sorry for the duplicated question. If I could trouble you a bit more though I'd like to ask what this row static bool lesserValue(const Card &lhs, const Card &rhs) actually does, since I don't quite understand it meself. – Alexander Granell Feb 20 '13 at 14:20
  • @AlexanderGranell It defines a static member function in the class. Static member functions "operate on the class rather than instances" - i.e. they don't have a `this` pointer inside them, and they can be invoked without an instance of the class (e.g. `return Card::lesserValue(myCard1, myCard2);` – Angew is no longer proud of SO Feb 20 '13 at 14:25
0

I came up with this answer, it uses compare classes, this also make it really easy to compare suites for instance. I also Improved public and private members in your class, since some values should not be public. And you class currently doesn't need a destructor.

#include<iostream> 
#include<algorithm> 
#include<vector> 

class Card {

    public:

        Card(int v, int s)
            :
                value(v),
                suite(s)
        {
        }

        /*No need for destructor*/

        int getValue(void) const { return value;}

        int getSuite(void) const { return suite;}

        void printCard(void) const {
            std::cout << "Value = " << value << "\tSuite = " << suite << std::endl;
        }

    private:
        /*these shouldn't be public*/
        int value;
        int suite;
};

class CompareCardValue {

    public:

        bool operator() ( const Card& c1, const Card& c2)
        {
            return c1.getValue() < c2.getValue();
        }
};

class CompareCardSuite{

    public:

        bool operator() ( const Card& c1, const Card& c2)
        {
            return c1.getSuite() < c2.getSuite();
        }
};

int main( ){

    std::vector<Card> deck;
    deck.push_back( Card(2,4) );
    deck.push_back( Card(1,3) );
    deck.push_back( Card(12,3) );
    deck.push_back( Card(8,2) );

    CompareCardSuite comp_suite; //compares for suite
    CompareCardValue comp_value; //compares for value

    /*We would like to use a const iterator since we are
     *not interested in changing the Card intances
     */
    std::vector<Card>::const_iterator it;
    for ( it = deck.begin(); it < deck.end(); it++){
        it->printCard();
    }
    std::cout << std::endl;

    /*sorting on value*/
    std::sort( deck.begin(), deck.end(), comp_value );

    for ( it = deck.begin(); it < deck.end(); it++){
        it->printCard();
    }

    std::cout << std::endl;
    /*sorting on suite*/
    std::sort( deck.begin(), deck.end(), comp_suite );

    for ( it = deck.begin(); it < deck.end(); it++){
        it->printCard();
    }
}
hetepeperfan
  • 4,292
  • 1
  • 29
  • 47