2016-09-26 2 views
0

mit struct Ich versuche, eine Karte zu verwenden, speichern Karteninformationen Koordinaten X, y als Schlüssel. Ich kann nicht richtig durch diese Map mit dem Auto-Iterator oder map.find() iterieren. Es wird mir einfach nicht den korrekten Kartenwert zurückgeben. Ich bin mit 14 C++, hier ist mein Stück Code:Cant eingefügte Werte in C++ Karte finden als Schlüssel

#include <iostream> 
#include <string> 
#include <map> 
#include <iterator> 
#include <vector> 

using namespace std; 

struct mapPoint { 
    int X; 
    int Y; 

    bool operator < (const mapPoint &coord) const { 
    if (X == coord.X && Y == coord.Y) { 
     return true; 
    } else { 
     return false; 
    } 
    } 
}; 

struct explorerNotes { 
    bool foundCoin; 
    int timesVisitedThisBlock; 
    vector<bool> unexploredEntrances; // 0 0 0 0 -> N S E W 
    explorerNotes():timesVisitedThisBlock(0),unexploredEntrances(4,false){} 
}; 

int main() { 
    map<mapPoint, explorerNotes> explorerNotebook; 

    explorerNotes testNote1, testNote2, testNote3; 
    mapPoint testCoord1, testCoord2, testCoord3; 

    testNote1.foundCoin = true; 
    testNote1.timesVisitedThisBlock = 42; 
    testNote1.unexploredEntrances = {true, true, false, false}; 
    testCoord1.X = 25; 
    testCoord1.Y = 3; 

    testNote2.foundCoin = false; 
    testNote2.timesVisitedThisBlock = 314; 
    testNote2.unexploredEntrances = {false, true, false, false}; 
    testCoord2.X = 11; 
    testCoord2.Y = 2; 

    testNote3.foundCoin = true; 
    testNote3.timesVisitedThisBlock = 420; 
    testNote3.unexploredEntrances = {false, true, false, false}; 
    testCoord3.X = 1; 
    testCoord3.Y = 1; 

    explorerNotebook.insert(pair<mapPoint, explorerNotes>(testCoord1, testNote1)); 
    explorerNotebook.insert(pair<mapPoint, explorerNotes>(testCoord2, testNote2)); 
    explorerNotebook.insert(pair<mapPoint, explorerNotes>(testCoord3, testNote3)); 

    map<mapPoint, explorerNotes>::iterator p; 
    p = explorerNotebook.find(testCoord1); 
    cout << " testing 1:" 
     << "\nfoundCoin: " << p->second.foundCoin 
     << "\ntimesVisitedThisBlock: " << p->second.timesVisitedThisBlock 
     << "\nunexploredEntrances: "<< "(" << p->second.unexploredEntrances[0] << "," << p->second.unexploredEntrances[1] << "," << p->second.unexploredEntrances[2] << "," <<p->second.unexploredEntrances[3] << ")" << endl; 

    map<mapPoint, explorerNotes>::iterator q; 
    q = explorerNotebook.find(testCoord2); 
    cout << " testing 2:" 
     << "\nfoundCoin: " << q->second.foundCoin 
     << "\ntimesVisitedThisBlock: " << q->second.timesVisitedThisBlock 
     << "\nunexploredEntrances: "<< "(" << q->second.unexploredEntrances[0] << "," << q->second.unexploredEntrances[1] << "," << q->second.unexploredEntrances[2] << "," <<q->second.unexploredEntrances[3] << ")" << endl; 

    map<mapPoint, explorerNotes>::iterator r; 
    r = explorerNotebook.find(testCoord3); 
    cout << " testing 3:" 
     << "\nfoundCoin: " << r->second.foundCoin 
     << "\ntimesVisitedThisBlock: " << r->second.timesVisitedThisBlock 
     << "\nunexploredEntrances: "<< "(" << r->second.unexploredEntrances[0] << "," << r->second.unexploredEntrances[1] << "," << r->second.unexploredEntrances[2] << "," <<r->second.unexploredEntrances[3] << ")" << endl;; 

    return 0; 
} 

Wenn ich diesen Code zu kompilieren es gab mir die Ausgabe:

testing 1: 
foundCoin: 1 
timesVisitedThisBlock: 42 
unexploredEntrances: (1,1,0,0) 
testing 2: 
foundCoin: 1 
timesVisitedThisBlock: 42 
unexploredEntrances: (1,1,0,0) 
testing 3: 
foundCoin: 1 
timesVisitedThisBlock: 42 
unexploredEntrances: (1,1,0,0) 

Er wiederholt nur den ersten Mehrwert .. Ich bin den ganzen Tag stecken geblieben. Irgendwelche Ideen? Danke im Voraus.

+3

Ihr 'Operator <' ist falsch. Es muss eine [strenge schwache Ordnung] implementieren (https://en.wikipedia.org/wiki/Weak_ordering#Strict_weak_orderings) –

+3

Sie könnten das Problem vermeiden, indem Sie 'std :: pair' oder' std :: tuple' die Umsetzung ' Operator <'. –

Antwort

4

Ihre operator < ist völlig durcheinander.

Sie sagen, dass A kleiner als B, wenn sein X-Koordinate gleich ist und dessen Y-Koordinate gleich ist. Also (1,1) < (2,2) ist falsch, aber (1,1) < (1,1) ist wahr. Kein Wunder, dass die Karte den richtigen Eintrag nicht finden kann.

Insbesondere:

  • da (1,1) < (2,2) falsch ist und (1,1)> (2,2) falsch ist (> Die < mit den Argumenten umgekehrt), dh (1,1) und (2,2) müssen gleich sein!
  • seit (1,1) < (1,1) ist wahr, (1,1)> (1,1) kann nicht wahr sein, weil eine Sache nicht kleiner und größer als eine andere Sache sein kann. Und doch ist es.

Sie müssen eine tatsächliche Reihenfolge für die Punkte herausfinden und diese Reihenfolge in operator < implementieren. Zum Beispiel könnte man sagen, dass (a, b) < (c, d) wenn ein < c, oder wenn a == c und b < d. Dann erhalten Sie, dass (1,1) < (1,2) < (1,3) < (2,0) < (2,1) < ...

bool operator < (const mapPoint &coord) const { 
    if (X < coord.X || (X == coord.X && Y < coord.Y)) { 
     return true; 
    } else { 
     return false; 
    } 
} 
+2

Verwenden Sie "binden", um '<' vernünftig zu schreiben. – Yakk

+0

Danke, es funktioniert. Ich ignorierte völlig die Tatsache, dass ich mit Operator RCO

3

Ihre < nicht als qualifiziert eine strenge schwache Ordnung. Also deinen Code steckt UB mal in die Map.

Die einfache Art und Weise ein konformes < ist, zu schreiben:

friend auto mytie(const mapPoint& self){ 
    return std::tie(self.X, self.Y); 
} 
friend bool operator<(const mapPoint& lhs, const mapPoint& rhs){ 
    return mytie(lhs)<mytie(rhs); 
} 

Wo wir delegieren <-tuple ‚s Implementierung ohne Kopien und mit maximaler DRY (Do not Repeat Yourself).

I < manuell finden zu tun ist einfach, aber fehleranfällig im Laufe der Jahrzehnte.

Verwandte Themen