std :: map keys в C ++ - PullRequest
       56

std :: map keys в C ++

1 голос
/ 10 апреля 2010

У меня есть требование создать две разные карты в C ++. Ключ имеет тип CHAR*, а значение является указателем на структуру. Я заполняю 2 карты этими парами, в отдельных итерациях. После создания обеих карт мне нужно найти все такие экземпляры, в которых значение строки, на которую ссылается CHAR*, одинаково.

Для этого я использую следующий код:

typedef struct _STRUCTTYPE
{
.. 
} STRUCTTYPE, *PSTRUCTTYPE;

typedef pair <CHAR *,PSTRUCTTYPE> kvpair;

..

CHAR *xyz;

PSTRUCTTYPE abc;

// after filling the information;

Map.insert (kvpair(xyz,abc));


// the above is repeated x times for the first map, and y times for the second map.
// after both are filled out;

std::map<CHAR *, PSTRUCTTYPE>::iterator Iter,findIter;

for (Iter=iteratedMap->begin();Iter!=iteratedMap->end();mapIterator++)
{
  char *key = Iter->first;

  printf("%s\n",key);

  findIter=otherMap->find(key);

  //printf("%u",findIter->second);

  if (findIter!=otherMap->end())
  {
    printf("Match!\n");
  }
}

Приведенный выше код не показывает соответствия, хотя в списке ключей на обеих картах указаны очевидные совпадения. Насколько я понимаю, оператор равенства для CHAR * просто уравнивает адрес памяти указателей.

У меня вопрос: что я должен сделать, чтобы изменить оператор равенства для этого типа ключа, или я могу использовать другой тип данных для строки?

Ответы [ 2 ]

4 голосов
/ 10 апреля 2010

Насколько я понимаю, оператор равенства для CHAR * просто равняет адрес памяти указателей.

Ваше понимание верно.

Самое простое, что можно сделать, это использовать std::string в качестве ключа. Таким образом, вы получите сравнения для фактического значения строки, работающего без особых усилий:

std::map<std::string, PSTRUCTTYPE> m;
PSTRUCTTYPE s = bar();
m.insert(std::make_pair("foo", s));

if(m.find("foo") != m.end()) {
    // works now
}

Обратите внимание, что вы можете потерять память для своих структур, если не всегда удаляете их вручную. Если вы не можете сохранить по значению, рассмотрите возможность использования умных указателей.

В зависимости от вашего варианта использования, вам не обязательно хранить указатели на структуры:

std::map<std::string, STRUCTTYPE> m;
m.insert(std::make_pair("foo", STRUCTTYPE(whatever)));

Последнее замечание: typedef структурирование того, как вы это делаете, является C-ism, в C ++ достаточно следующего:

typedef struct STRUCTTYPE {
    // ...
} *PSTRUCTTYPE;
0 голосов
/ 10 апреля 2010

Если вы используете std::string вместо char *, вы можете использовать более удобные функции сравнения. Кроме того, вместо написания собственного кода соответствия ключей вы можете использовать алгоритм STL set_intersection (подробнее см. здесь ), чтобы найти общие элементы в двух отсортированных контейнерах (конечно же, std::map ). Вот пример

typedef map<std::string, STRUCTTYPE *> ExampleMap;  
ExampleMap inputMap1, inputMap2, matchedMap;

// Insert elements to input maps
inputMap1.insert(...);

// Put common elements of inputMap1 and inputMap2 into matchedMap
std::set_intersection(inputMap1.begin(), inputMap1.end(), inputMap2.begin(), inputMap2.end(), matchedMap.begin());

for(ExampleMap::iterator iter = matchedMap.begin(); iter != matchedMap.end(); ++iter)
{
    // Do things with matched elements
    std::cout << iter->first << endl;
}
...