0

I would like to sort different types of numbers in different files as a learning exercise. I've managed to get doubles and ints to sort correctly, but cannot get my own type (to sort a deck of cards) to format correctly. I've managed to get it narrowed down to my sort function in the Reader Class. I'm getting all sorts of errors. What exactly am I doing wrong? Or am I missing something? Thanks everyone, I hope I explained my problems clearly.

My file I created for Cards looks something like...

1 11 (meaning Jack of Diamonds)

2 8 (meaning 8 of hearts)

etc...

errors:

error: no match for 'operator<' in '((Reader)this)->Reader::array[compareIndex] < ((Reader)this)->Reader::array[smallestIndex]'

error: cannot convert 'Card' to 'int' in initialization

error: no match for 'operator=' in '((Reader*)this)->Reader::array[smallestIndex] = temp'

My Code

Lastly, Main

#include <iostream>
#include "Reader.h"
#include "Card.h"

using namespace std;


int main() {

    Reader<int> nums;
    Reader<double> dubs;
    Reader<Card> cards;
    int number;

    do {

        cout << "Enter 1 if your file contains integers\n"
           << "Enter 2 if your file contains doubles\n"
           << "Enter 3 if your file contains Cards:\n"
           << "Enter a number: ";
        cin >> number;

        if (number == 1){
            nums.open_IO();
            nums.read_array();
            nums.sort();
            nums.write_array();
            nums.close_IO();
        } else if (number == 2){
            dubs.open_IO();
            dubs.read_array();
            dubs.sort();
            dubs.write_array();
            dubs.close_IO();
        } else if (number == 3){
            cards.open_IO();
            cards.read_array();
            cards.sort();
            cards.write_array();
            cards.close_IO();
        }

    } while ((number != 1) && (number != 2) && (number != 3));


}

Reader.h

#ifndef READER_H
#define READER_H
#include <string>
#include <fstream>
using namespace std;

template <class rList>
class Reader {
 public:
    static const int SIZE = 50;

      Reader();

      bool open_IO();

      void close_IO();

      bool read_array();

      bool write_array();

      void sort();


 private:
      // Ask for the files
      void ask_filenames();

      rList array[SIZE];
      int readSize;

      // input file names and stream to get the data
      string readFileName;
      ifstream inFile;

      // output file names and stream to get the data
      string writeFileName;
      ofstream outFile;
      bool askedFileNames;
    };

#endif

#include "Reader.cpp"

My Reader.Cpp file

// File: Reader.cpp
#ifndef READER_CPP
#define READER_CPP
#include "Reader.h"
#include <iostream>
using namespace std;

/***************************************************************************
 * Contructors and modifying functions defined in "Reader.h"
***************************************************************************/


template <class rList>
Reader<rList>::Reader() {
  askedFileNames = false;
  readFileName = "";
  writeFileName = "";
  readSize = 0;
  rList empty;
  for( int i = 0; i<SIZE; i++ ) array[i]=empty;
}

template <class rList>
bool Reader<rList>::open_IO(){
    if(!askedFileNames) ask_filenames();

    inFile.open(readFileName.c_str()); //we can't pass a string, we need a char array
    if(!inFile.is_open()) {
        return false;
    }
    outFile.open(writeFileName.c_str());
    if(!outFile.is_open()) {
        inFile.close(); //inFile opened successfully so it needs to be closed now
        return false;
    }
    return true;
}

template <class rList>
void Reader<rList>::close_IO() {
    inFile.close();
    outFile.close();
}

template <class rList>
bool Reader<rList>::read_array() {
    if(inFile.is_open()) {
        inFile >> readSize;
        int index = 0;
        while(!inFile.eof() && index < readSize) {
            inFile >> array[index++]; //increments index after assigning value
        }
        readSize = index; //the input file could have had fewer numbers so set readSize
        return true;
    }
    return false;
}

template <class rList>
bool Reader<rList>::write_array() {
    if(outFile.is_open()) {
        outFile << readSize << endl;
       //don't forget the number indicating the element co
        int index = 0;
        while(index < readSize) {
            outFile << array[index++] << endl;
        }
        return true;
    }
    return false;
}

template <class rList>
void Reader<rList>::sort() {
    int startIndex = 0;
    int compareIndex;
    int smallestIndex;
    bool smallerFound;
    while(startIndex < readSize) {
        smallestIndex = startIndex;
        compareIndex = startIndex + 1;
        smallerFound = false;
        while(compareIndex < readSize) { //find the smallest value from the starting index
            if(array[compareIndex] < array[smallestIndex]) {
                smallestIndex = compareIndex;
                smallerFound = true;
            }
            compareIndex++;
        }
        if(smallerFound) { //only swap the values if a smaller value is found
            int temp = array[startIndex];
            array[startIndex] = array[smallestIndex];
            array[smallestIndex] = temp;
        }
        startIndex++;
    }
}

/*--------------------------------------------------------------
  This function asks the user for the filenames. This operation
  is placed in a separate function because it is called multiple
  times.
  --------------------------------------------------------------*/
template <class rList>
void Reader<rList>::ask_filenames() {
  cout << "Welcome. Please type in the name of the file to read the numbers.\n";
  cin >> readFileName;
  cout << "Thank you. Please type in the name of the file to write the numbers.\n";
  cin >> writeFileName;
  askedFileNames = true;
}

#endif

Card.h

#include <ostream>
#include <string>
#include "Reader.h"

using namespace std;

class Card{
 public:
    static const int SIZE = 50;
    enum SUIT {clubs, diams, hears, spads };
    enum RANK {ace=1, two, thr, fou, fiv, six, sev, eig, nin, ten, jac, que, kin};

    Card();

    Card(int newSuit, int newRank);

    void change(int newSuit, int newRank);

    friend ostream& operator << ( ostream& out, Card theCard );
    friend istream& operator >> ( istream& in, Card theCard );

 private:
    void change_rank(int newRank);

    void change_suit(int newSuit);

    string get_rank() const;

    string get_suit() const;

    SUIT suit;
    RANK rank;


};

Card.cpp

    #include <iostream>
#include <string>
#include "Card.h"

using namespace std;

Card::Card() { suit = spads; rank = ace; }

Card::Card(int newSuit, int newRank) {
    change(newSuit, newRank);
}

void Card::change( int newSuit, int newRank ) {
    change_suit( newSuit );
    change_rank( newRank );
}


ostream& operator << ( ostream& out, Card theCard ) {
  out << theCard.get_rank() << " of " << theCard.get_suit();
  return out;
}

istream& operator >> ( istream& in, Card theCard ) {
    int aSuit;
    int aRank;

    in >> aSuit >> aRank;
    return in;
}


// private member functions to set the private variables with their
// corresponding values: integer input -> enumerated type;
void Card::change_rank( int newRank ) {
    if( newRank == ace ) rank = ace;
    else if( newRank == two ) rank = two;
    else if( newRank == thr ) rank = thr;
    else if( newRank == fou ) rank = fou;
    else if( newRank == fiv ) rank = fiv;
    else if( newRank == six ) rank = six;
    else if( newRank == sev ) rank = sev;
    else if( newRank == eig ) rank = eig;
    else if( newRank == nin ) rank = nin;
    else if( newRank == ten ) rank = ten;
    else if( newRank == jac ) rank = jac;
    else if( newRank == que ) rank = que;
    else if( newRank == kin ) rank = kin;
}

void Card::change_suit( int newSuit ) {
    if( newSuit == clubs ) suit = clubs;
    else if( newSuit == spads ) suit = spads;
    else if( newSuit == diams ) suit = diams;
    else if( newSuit == hears ) suit = hears;
}

  // Private member functions to extract the information from the card
  // class.
string Card::get_rank() const {
    if( rank == ace ) return "ace";
    if( rank == two ) return "two";
    if( rank == thr ) return "three";
    if( rank == fou ) return "four";
    if( rank == fiv ) return "five";
    if( rank == six ) return "six";
    if( rank == sev ) return "seven";
    if( rank == eig ) return "eight";
    if( rank == nin ) return "nine";
    if( rank == ten ) return "ten";
    if( rank == jac ) return "jack";
    if( rank == que ) return "queen";
    if( rank == kin ) return "king";
    return "get_rank: error";
}

string Card::get_suit() const {
    if( suit == diams ) return "D";
    if( suit == hears ) return "H";
    if( suit == spads ) return "S";
    if( suit == clubs ) return "C";
    return "get_suit: error";
}
4

2 回答 2

2

如果您使用 astd::vector<Card>而不是 C 数组,并且重载operator<了 for Card,则可以让标准库为您洗牌和排序。

vector<T>是标准库自带的容器。它是一个类模板,可以存储 type 的元素TT可以是数字类型,astd::string甚至是 a structor class

以下是您如何重载小于运算符的方法Card

bool Card::operator<(const Card& other)
{
    return true if this card is smaller than the other card;
    // You may want to order by rank, then by suit, or vice-versa.
}

定义此运算符后,标准库容器和算法现在将“知道”如何订购您的Cards.

这是您如何使用 a vectorof Cards 的方法。

std::vector<Card> deck(52); // Initially sized to 52 elements
// Populate deck just like you would an array
deck[0] = Card(diams, ace);
etc...

// Sort the deck
std::sort(deck.begin(), deck.end());

// Shuffle the deck
std::random_shuffle(deck.begin(), deck.end());

// Get the 5th card in the deck
Card fifth = deck[4];

std::sort使用快速排序算法,它比您编写的冒泡排序要快得多(无意冒犯:-)。很难编写可以超越标准库提供的手工数据结构和算法。编译器编写者花费数年时间来完善和调整他们的标准库实现。

当您使用标准库容器时,您可以使用大量标准库算法。这使您可以专注于解决问题,而不是一遍又一遍地重写相同的基本算法和数据结构。

于 2012-09-02T22:52:05.160 回答
1

您需要为Card

class Card{
 public:
  friend bool operator< ( const Card &left, const Card &right ) {
     ... 
  }

你有一个错字。

    if(smallerFound) { //only swap the values if a smaller value is found
        int temp = array[startIndex];
        array[startIndex] = array[smallestIndex];
        array[smallestIndex] = temp;
    }

应该

    if(smallerFound) { //only swap the values if a smaller value is found
        rList temp = array[startIndex];
        array[startIndex] = array[smallestIndex];
        array[smallestIndex] = temp;
    }

或更简单地说

    if(smallerFound) { //only swap the values if a smaller value is found
        std::swap( array[startIndex], array[smallestIndex] );
    }
于 2012-09-02T22:48:04.373 回答