2016-09-26 1 views
0

지도를 사용하여 x, y 좌표를 사용하여지도 정보를 저장하려고합니다. 필자는 auto iterator 또는 map.find()를 사용하여이 맵을 올바르게 반복 할 수 없습니다. 그것은 나에게 정확한지도 값을 돌려주지 않을 것이다. 이 코드를 컴파일 할 때구조체를 키로 사용하여 C++ 맵에 삽입 된 값을 찾습니다.

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

이 나에게 출력을 주었다 : 여기의 코드 내 체크입니다, C++ 14을 사용하고 그냥 처음 부가가치를 반복

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) 

.. 하루 종일 붙어있어. 어떤 아이디어? 미리 감사드립니다.

+3

'연산자 <'가 잘못되었습니다. [strict weak ordering]을 구현해야합니다 (https://en.wikipedia.org/wiki/Weak_ordering#Strict_weak_orderings) –

+3

'std :: pair' 또는'std :: tuple'을 사용하여이 문제를 피할 수 있습니다. 연산자 <'. –

답변

4

operator <은 완전히 엉망입니다.

X 좌표가 같고 Y 좌표가 동일하면 A가 B보다 작다고 말합니다. 따라서 (1,1) < (2,2)은 거짓이지만 (1,1) < (1,1)은 참입니다. 지도가 올바른 항목을 찾을 수 없다는 것은 놀라운 일이 아닙니다. 특히

(1,1) < (2,2)가 거짓이고, (1,1)> (2,2)이 거짓이므로

  • (>를 인수 < 역전되고), 그것은 (1,1)과 (2,2)가 동일해야 함을 의미합니다!
  • (1,1) < (1,1)이 참이므로 (1,1)> (1,1)은 참일 수 없습니다. 한 가지가 다른 것보다 작을 수 없기 때문입니다. 그렇다.

포인트의 실제 순서를 알아 내고 해당 순서를 operator <에 구현해야합니다. 예를 들어 <c 또는 a == c이고 b가 < 인 경우 (a, b) < (c, d)라고 말할 수 있습니다. 그럼 당신은 그 (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

'tie '를 써서'<'를 써라. – Yakk

+0

감사합니다. 작동합니다. 나는 연산자를 다루고 있다는 사실을 완전히 무시했다 < – RCO

3

귀하의 <는 자격이되지 않습니다 얻을 엄격한 약한 명령. 따라서 코드는 UB를 맵에 넣으면됩니다.

순응 <를 작성하는 쉬운 방법은 다음과 같습니다

우리가 < 사본없이 구현 tuple의에와 최대 건조로 (중복 배제) 위임
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); 
} 

.

나는 <을 수동으로 수행하는 것이 쉽지만 수십 년 동안 오류가 발생하는 것으로 나타났습니다.

관련 문제