尝试对自定义对象使用std::sort()

Trying to use std::sort() with custom objects

本文关键字:std sort 自定义 对象      更新时间:2023-10-16

我在网上查了一些教程。我已经试过了,但问题是std::sort()不执行任何东西!下面是我的全部代码:

#include <string>
#include <iostream>
#include <iomanip>
#include <sstream> 
#include <algorithm>
#include <vector>
using namespace std;
#ifndef _card_h
#define _card_h
enum Suit {
    CLUBS, DIAMONDS, HEARTS, SPADES
};
enum Rank {
    TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, JACK, QUEEN, KING, ACE
};
class Card {
    public:
        Card();
        Card(Rank, Suit);
        ~Card();
        Rank GetRank();
        Suit GetSuit();
        string ToString();
    private:
        Rank rank;
        Suit suit;
};
#endif
Card::Card() {
}
Card::Card(Rank rank, Suit suit) {
    this->rank = rank;
    this->suit = suit;
}
Card::~Card() {}
Rank Card::GetRank() {
    return rank;
}
Suit Card::GetSuit() {
    return suit;
}
string Card::ToString() {
    string cardName = "";
    switch (rank) {
        case TWO   : cardName += "2"; break;
        case THREE : cardName += "3"; break;
        case FOUR  : cardName += "4"; break;
        case FIVE  : cardName += "5"; break;
        case SIX   : cardName += "6"; break;
        case SEVEN : cardName += "7"; break;
        case EIGHT : cardName += "8"; break;
        case NINE  : cardName += "9"; break;
        case TEN   : cardName += "T"; break;
        case JACK  : cardName += "J"; break;
        case QUEEN : cardName += "Q"; break;
        case KING  : cardName += "K"; break;
        case ACE   : cardName += "A"; break;
    }
    switch (suit) {
        case CLUBS    : cardName += "C"; break;
        case DIAMONDS : cardName += "D"; break;
        case HEARTS   : cardName += "H"; break;
        case SPADES   : cardName += "S"; break;
    }
    return cardName;
}
#ifndef _cardcomparer_h
#define _cardcomparer_h
class CardComparer {  
    public:
        bool operator() (Card*, Card*);
    private:
        Card* firstCard;
        Card* secondCard;
};
#endif
bool CardComparer::operator() (Card* firstCard, Card* secondCard) {
    this->firstCard = firstCard;
    this->secondCard = secondCard;
    cout << "in Cardcompare! " << endl;
    if (firstCard->GetRank() == secondCard->GetRank()) {
        return firstCard->GetSuit() > secondCard->GetSuit();
    }
    else {
        return firstCard->GetRank() > secondCard->GetRank();
    }
}
#ifndef _hand_h
#define _hand_h
const int CARDS_IN_HAND = 5;
class Hand {
    public:
        Hand(int);
        ~Hand();
        void AddCard(Card*);
        string ToString();
    private:
        int cardCount;
        int playerID;
        vector<Card*> cards;
};
#endif
Hand::Hand(int playerID) {
    this->playerID = playerID;
    cards.reserve(CARDS_IN_HAND);
    cardCount = 0;
}
Hand::~Hand() {
    cards.clear();
}
void Hand::AddCard(Card* newCard) {
    cards[cardCount] = newCard;
    cardCount++;
    sort(cards.begin(), cards.end(),CardComparer());
}
string Hand::ToString() {
    stringstream playerCards;
    playerCards << "Player " << this->playerID << " -";
    for (int i = 0; i < cardCount; i++ ){
        playerCards << " " << cards[i]->ToString();
    }
    return playerCards.str();
}
int main() {
    vector<Hand*> hands;
    hands.reserve(1);
    hands[0] = new Hand(0);
    hands[0]->AddCard(new Card((Rank)4, (Suit)1));
    hands[0]->AddCard(new Card((Rank)8, (Suit)2));
    hands[0]->AddCard(new Card((Rank)5, (Suit)1));
    hands[0]->AddCard(new Card((Rank)2, (Suit)0));
    hands[0]->AddCard(new Card((Rank)7, (Suit)3));
    cout << hands[0]->ToString() << endl;
    return 0;
}

问题是第133行(sort(cards.begin(), cards.end(),CardComparer());)没有执行。无论我把它注释掉还是在结果中没有改变,我甚至在93(cout << "in Cardcompare! " << endl;)上添加了额外的行,如果它使用bool,它会打印出一些东西。然而,事实并非如此。我找不到问题在哪里。这里的问题是什么,我该如何解决它?

问题是向量不知道您试图在AddCard中添加卡片,或者更准确地说,您没有真正添加这些卡片,因为您没有调用push_back,而是简单地将指针放在内存中的某个地方。是的,由于调用reserve,向量拥有该内存,但它认为它是空的。因此,begin()end()给出了相同的迭代器,并对0个元素进行排序。

在你选择的教科书中查找有关vector和其他容器的章节。您不需要跟踪卡片的数量(cardCount),因为如果使用得当,矢量可以完美地为您完成此操作。

您的代码中有许多问题需要解决。其中最重要的一个事实是,您当前正在泄漏大量内存。您正在声明vector<Card*>并分配内存,但从未释放它。此外,你输入数据到你的向量的方式是不正确的。reserve函数实际上并不创建新元素,它只是为它们保留内存。

这是一个清理后的版本,包括让你的排序正确工作。希望通过学习它,你能学到一些关于c++的知识。

#include <string>
#include <iostream>
#include <iomanip>
#include <sstream> 
#include <algorithm>
#include <vector>
#include <memory>
using namespace std;
enum Suit {
    CLUBS, DIAMONDS, HEARTS, SPADES
};
enum Rank {
    TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, JACK, QUEEN, KING, ACE
};
const char *card_lookup[] = {"2", "3", "4", "5", "6", "7", "8", "9", "T", "J", "Q", "K", "A"};
const char *suit_lookup[] = {"C", "D", "H", "S" };
class Card {
    public:
        Card::Card() 
        { }
        Card::Card(Rank rank, Suit suit) 
        {
            this->rank = rank;
            this->suit = suit;
        }
        Card::~Card() 
        {}
        Rank Card::GetRank() const
        {
            return rank;
        }
        Suit Card::GetSuit() const
        {
            return suit;
        }
        string Card::ToString() {
            string cardName = card_lookup[rank];
            cardName += suit_lookup[suit];
            return cardName;
        }
    private:
        Rank rank;
        Suit suit;
};
bool operator<(const Card& lhs, const Card& rhs)
{
    if(lhs.GetRank() == rhs.GetRank())
        return lhs.GetSuit() < rhs.GetSuit();
    else
        return lhs.GetRank() < rhs.GetRank();
}
const int CARDS_IN_HAND = 5;
class Hand {
    public:
        Hand::Hand(int playerID) 
        {
            this->playerID = playerID;
        }
        Hand::~Hand() 
        { }
        void Hand::AddCard(Card newCard) 
        {
            cards.push_back(newCard);
        }
        string Hand::ToString() 
        {
            sort(cards.begin(), cards.end());
            stringstream playerCards;
            playerCards << "Player " << this->playerID << " -";
            for (auto it = cards.begin(), end = cards.end(); it != end; ++it)
                playerCards << " " << it->ToString();
            return playerCards.str();
        }
    private:
        int playerID;
        vector<Card> cards;
};

int main() {
    vector<Hand> hands;
    Hand h(1);
    h.AddCard(Card(SIX, DIAMONDS));
    h.AddCard(Card(TEN, HEARTS));
    h.AddCard(Card(SEVEN, DIAMONDS));
    h.AddCard(Card(FOUR, CLUBS));
    h.AddCard(Card(NINE, SPADES));
    hands.push_back(h);
    cout << hands[0].ToString() << endl;
    return 0;
}