ProgramingTip

std :: map에서 char *를 키로 사용

bestdevel 2020. 10. 20. 07:57
반응형

std :: map에서 char *를 키로 사용


다음 코드가 작동하지 않는 이유를 알아 내려고 노력하고 외침 문자 *를 키 유형으로 사용하는 데 문제가 있는지 또는 왜 발생하는지 잘 모르겠습니다. 내가 사용하는 다른 모든 기능 (HL2 SDK에서)이 사용 char*하는 사용 std::string하면 불필요한 합병증이 많이 발생합니다.

std::map<char*, int> g_PlayerNames;

int PlayerManager::CreateFakePlayer()
{
    FakePlayer *player = new FakePlayer();
    int index = g_FakePlayers.AddToTail(player);

    bool foundName = false;

    // Iterate through Player Names and find an Unused one
    for(std::map<char*,int>::iterator it = g_PlayerNames.begin(); it != g_PlayerNames.end(); ++it)
    {
        if(it->second == NAME_AVAILABLE)
        {
            // We found an Available Name. Mark as Unavailable and move it to the end of the list
            foundName = true;
            g_FakePlayers.Element(index)->name = it->first;

            g_PlayerNames.insert(std::pair<char*, int>(it->first, NAME_UNAVAILABLE));
            g_PlayerNames.erase(it); // Remove name since we added it to the end of the list

            break;
        }
    }

    // If we can't find a usable name, just user 'player'
    if(!foundName)
    {
        g_FakePlayers.Element(index)->name = "player";
    }

    g_FakePlayers.Element(index)->connectTime = time(NULL);
    g_FakePlayers.Element(index)->score = 0;

    return index;
}

비교 펑터를 맵에 제공해야합니다. 문맥 포인터가 null로 끝나는 언어가 아닌 포인터를 비교합니다. 일반적으로지도 키가 포인터가되기를 원하는 경우입니다.

예를 들면 :

struct cmp_str
{
   bool operator()(char const *a, char const *b) const
   {
      return std::strcmp(a, b) < 0;
   }
};

map<char *, int, cmp_str> BlahBlah;

절대적으로 100 % 확신하지 않는 똑같은 포인터로char* 지도에 접근 할 수 없습니다 .

예 :

char *s1; // pointing to a string "hello" stored memory location #12
char *s2; // pointing to a string "hello" stored memory location #20

로지도에 액세스하면로 액세스 s1하는 것과 다른 위치가 s2있습니다.


두 개의 C 스타일의 주소를 사용할 수 있습니다. 그리고 그것은 map내용이 아닌 포인터 비교합니다.

로 전환하는 데 필요한 비용은 std::map<std::string, int>생각만큼 많지 않을 수 있습니다.

정말로 그러나 const char*맵 키로 사용해야하는 경우 다음을 시도하십시오.

#include <functional>
#include <cstring>
struct StrCompare : public std::binary_function<const char*, const char*, bool> {
public:
    bool operator() (const char* str1, const char* str2) const
    { return std::strcmp(str1, str2) < 0; }
};

typedef std::map<const char*, int, StrCompare> NameMap;
NameMap g_PlayerNames;


작업 할 수으로는 std::map<const char*, int>있지만 const포인터가 아닌 것을 사용해서는 안됩니다 ( const키에 추가 된 문자열에 유의하십시오 ). 맵에서 키로 참조하는 곳에서 변경됩니다. (는 키를지도 만들어 키를 보호하지만 const이것은 포인터가 가리키는 문자열이 아닌 포인터 만 구성합니다 .)

하지만 단순히 사용하지 않는 이유는 std::map<std::string, int>무엇입니까? 그것은 두통없이 즉시 작동합니다.


a char *를 사용하여 문자열을 사용하여 비교하고 있습니다. 그들은 동일하지 않습니다.

A char *는 char에 대한 포인터입니다. 궁극적으로 값이에 대한 유효한 주소로 해석되는 정수 유형입니다 char.

문자열은 문자열입니다.

컨테이너는 올바르게 작동하지만 키가 a char *이고 값이 int.


다른 사람들이 말했듯이, 실제로 필요한 경우 포인터를 키로 사용하는 원칙적으로 잘못된 것이 없지만이 경우에는 char * 대신 std :: string을 사용해야합니다.

이 코드가 작동하지 않는 또 다른 이유는 맵에서 사용 가능한 항목을 찾으면 동일한 키 (char *)를 사용하여 맵에 다시 삽입하려고하기 때문이라고 생각합니다. 해당 키가 이미 맵에 있으므로 삽입이 실패합니다. map :: insert ()의 표준은이 동작을 정의합니다 ... 키 값이 존재하면 삽입이 실패하고 매핑 된 값은 변경되지 않습니다. 그런 다음 어쨌든 삭제됩니다. 먼저 삭제 한 다음 다시 삽입해야합니다.

char *를 std :: string으로 변경하더라도이 문제는 남아 있습니다.

이 스레드가 꽤 오래되었다는 것을 알고 있으며 지금까지 모든 문제를 해결했지만 아무도이 문제를 제기하지 않았으므로 앞으로의 시청자를 위해 대답하겠습니다.


여러 소스 파일에서 요소를 찾으려고 할 때 char *를 맵 키로 사용하는 데 어려움을 겪었습니다. 요소가 삽입 된 동일한 소스 파일 내에서 모든 액세스 / 찾기가 제대로 작동합니다. 그러나 다른 파일에서 찾기를 사용하여 요소에 액세스하려고하면 확실히 맵 내부에있는 요소를 가져올 수 없습니다.

그 이유는 Plabo가 지적한 것처럼 포인터 (모든 컴파일 단위에는 자체 상수 char *가 있음)가 다른 cpp 파일에서 액세스 될 때 전혀 동일하지 않기 때문입니다.


이 비교 (지원하는만큼 어떤 키 유형을 사용하는 아무 문제가 없다 <, >, ==) 및 할당.

언급해야 할 한 가지 사항- 템플릿 클래스를 사용하고 있다는 점을 고려하십시오 . 결과적으로 컴파일러는 char*및에 대해 두 가지 다른 인스턴스화를 생성합니다 int*. 두 가지 의 실제 코드 는 사실상 동일합니다.

따라서을 void*키 유형으로 사용한 다음 필요에 따라 캐스팅하는 것을 고려 합니다. 제 의견입니다.

참고 URL : https://stackoverflow.com/questions/4157687/using-char-as-a-key-in-stdmap

반응형