2012-09-02 5 views
0

학습용으로 다른 파일에서 여러 유형의 숫자를 정렬하고 싶습니다. 나는 double과 int를 올바르게 정렬 할 수 있었지만, 형식을 올바르게 지정하기 위해 자신의 형식 (카드 덱을 정렬하기 위해)을 얻을 수는 없습니다. 나는 그것을 Reader 클래스에 내 정렬 기능으로 축소 할 수있었습니다. 모든 종류의 오류가 발생합니다. 정확히 내가 뭘 잘못하고 있니? 또는 나는 무엇인가 놓치고 있냐? 모두들 고마워요. 제 문제를 분명하게 설명했으면 좋겠습니다. ,C++ 템플릿 및 클래스

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'

내 코드

마지막 : 나는 카드에 대해 생성

내 파일

오류 ... ...

1 11 (meaning Jack of Diamonds) 

2 8 (meaning 8 of hearts) 

등 뭔가처럼 보이는 기본

#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" 

내 Reader.Cpp는 파일

// 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"; 
} 
+0

이러한 오류는 줄 번호와 함께 있다고 가정합니다. 일부 연산자를 오버로드해야 정렬 할 수 있으며 오류는 어디에서 어떤 연산자를 오버로드해야하는지 알려줍니다. 암시 적으로 수행 할 수없는 int에 카드를 캐스팅하려고 시도하므로 이러한 변환을 명시해야합니다. – Benjamin

+0

젠장, 그 말이 맞는 것 같아. 내가 프로그래밍 한 이후로 오랫동안 해왔다. 나는 그것을 잊어 버렸다. 정확히 어떻게 다시 할 수 있습니까? – Lindsiria

답변

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; 
    } 

또는 당신이 std::vector<Card> 대신 C 배열의 사용, 당신은 Card에 대한 operator< 오버로드하면 더 간단하게

if(smallerFound) { //only swap the values if a smaller value is found 
     std::swap(array[startIndex], array[smallestIndex]); 
    } 
+0

이 오류조차 알지 못했습니다. 감사. 친구 와부하 기능을 이해했다고 생각합니다. 모든 것에 감사드립니다. – Lindsiria

2

해야합니다, 당신은 표준 라이브러리를 얻을 수 있습니다 데크를 섞어서 정렬 해주세요.

vector<T>컨테이너 표준 라이브러리와 함께 제공됩니다. 이것은 T 유형의 요소를 저장할 수있는 클래스 템플릿입니다. T은 숫자 유형, std::string 또는 struct 또는 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를 주문하는 방법을 "알고있다"것입니다.

vectorCard 초까지 사용하는 방법은 다음과 같습니다.

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

없이 공격 :-) (당신이 작성한 버블 정렬보다 훨씬 빠릅니다 퀵 알고리즘을 사용합니다. 표준 라이브러리가 제공하는 것을 능가하는 수작업 데이터 구조 및 알고리즘을 작성하는 것은 어렵습니다. 컴파일러 작성자는 표준 라이브러리 구현을 완성하고 조정하는 데 수년을 보냈습니다.

표준 라이브러리 컨테이너를 사용하는 경우 표준 라이브러리 알고리즘을 사용할 수 있습니다. 따라서 문제를 해결하는 데 집중할 수 있으며 동일한 기본 알고리즘과 데이터 구조를 반복해서 다시 작성하지 않아도됩니다.

+0

기본 작동을 얻으면 벡터 사용을 계획합니다. 나는 곧 벡터에 대해 더 많이 배우고 싶다. 감사합니다 – Lindsiria

+1

+1 좋은 답변. 그러나 게으른 사람이라면'std :: set '을 사용할 수 있습니다. – bitmask

+1

@bitmask : 연관 컨테이너이기 때문에'std :: set '을 섞어 쓸 수 없습니다. –