密钥比较的最佳方式(C ++地图)

时间:2014-03-20 12:28:43

标签: c++ map comparison

在使用地图时,我在定义比较函数时遇到了一些问题,因为我使用自己的数据类型插入地图。例如,目前我有这样的结构:

typedef struct triple_key{
    int int_key;
    struct some_data;
    unsigned char char_array_key[16];
}triple_key;

其中some_data是这样的:

struct some_data{
    int data_length;
    unsigned char* data;
}

为了比较,我覆盖了operator(),我的想法是执行以下操作:

class comp_triple_key{
public:
bool operator()(const triple_key &x, const triple_key &y){
    if(x.int_key!= y.int_key){
        return x.int_key<y.int_key;
    }
    else{
       if(memcmp((x.some_data).data, (y.some_data).data, (x.some_data).data_length) != 0){
          return memcmp((x.some_data).data, (y.some_data).data, (x.some_data).data_length) < 0;
       }
       else{
           return memcmp((x.char_array_key), (y.char_array_key), 16*sizeof(char))<0;
       }
   }
};

};

然后地图如下:

 std::map<triple_key,int,comp_triple_key> my_map;

有没有更好的方法来比较这些多个键值?在大多数情况下,这是有效的(并且工作正常),但有时我会得到断言:

Expression: invalid operator <

我过去曾经处理过这个问题,但我不清楚如何一般地避免这个问题,或者通常使用哪种方法来确保它适用于所有情况。

3 个答案:

答案 0 :(得分:2)

有几件事要做:

  • 改为定义比较器类(在您的情况下为comp_triple_key),为triple_key定义operator<

这样的工作:

  bool operator<(const triple_key &x, const triple_key &y){
    if(x.int_key!= y.int_key){
        return x.int_key<y.int_key;
    }
    else{
       if(memcmp((x.somedata).data, (y.somedata).data, (x.somedata).data_length) != 0){
          return memcmp((x.somedata).data, (y.somedata).data, (x.somedata).data_length) < 0;
       }
       else{
           return memcmp((x.char_array_key), (y.char_array_key), 16*sizeof(char))<0;
       }
    }
  }

然后你可以创建像:

这样的对象
std::map<triple_key,int> my_map;

可编辑示例(问题中的固定代码):

#include <map>
#include <iostream>
#include <string>
#include <string.h>


struct some_data{
    int data_length;
    unsigned char* data;
};

struct triple_key{
    int int_key;
    some_data somedata ;
    unsigned char char_array_key[16];
};

  bool operator<(const some_data &x, const some_data &y){
    if(x.int_key!= y.int_key){
        return x.int_key<y.int_key;
    }
    else{
       if(memcmp((x.somedata).data, (y.somedata).data, (x.somedata).data_length) != 0){
          return memcmp((x.somedata).data, (y.somedata).data, (x.somedata).data_length) < 0;
       }
       else{
           return memcmp((x.char_array_key), (y.char_array_key), 16*sizeof(char))<0;
       }
    }
  }

  bool operator<(const triple_key &x, const triple_key &y){
    if(x.int_key!= y.int_key){
        return x.int_key<y.int_key;
    }
    else{
       if(memcmp((x.somedata).data, (y.somedata).data, (x.somedata).data_length) != 0){
          return memcmp((x.somedata).data, (y.somedata).data, (x.somedata).data_length) < 0;
       }
       else{
           return memcmp((x.char_array_key), (y.char_array_key), 16*sizeof(char))<0;
       }
    }
  }

int main()
{
    std::map<triple_key,int> my_map;
}

答案 1 :(得分:1)

越简越好。只需逐一比较这个方案:

bool operator()(const triple_key &x, const triple_key &y){
   if (x.int_key < y.int_key)  
     return true;
   if (y.int_key < x.int_key)
     return false;
   if (lexicographical_compare(x.some_data.data, x.some_data.data + x.some_data.data_length,
                               y.some_data.data, y.some_data.data + y.some_data.data_length))
      return true;
   if (lexicographical_compare(y.some_data.data, y.some_data.data + y.some_data.data_length,
                               x.some_data.data, x.some_data.data + x.some_data.data_length))
      return false;
   return memcmp(x.char_array_key, y.char_array_key, sizeof(y.char_array_key)) < 0; 
}

答案 2 :(得分:0)

#include <iostream>
#include <memory>
#include <map>
using namespace std;
struct some_data{
    int data_length;
    unsigned char* data;

    bool operator < (const some_data& other) const
    {
        if (memcpy(data, other.data, data_length)  < 0)
            return true;
        else
            return false;
    }
};

typedef struct triple_key{
    int int_key;
    struct some_data data;
    unsigned char uuid[16];

    bool operator < (const triple_key& other) const
    {
        if (int_key < other.int_key)
            return true;
        else
        {
            if (data < other.data)
                return true;
            else
            {
                if (memcpy((void*)uuid, (void*)other.uuid, sizeof(uuid)) < 0)
                    return true;
            }
        }

        return false;
    }
}triple_key;

int main()
{
    some_data data1;
    data1.data = (unsigned char *)malloc(4);
    data1.data_length = 4;

    some_data data2;
    data2.data = (unsigned char *)malloc(5);
    data2.data_length = sizeof(5);

    triple_key key1;
    key1.int_key = 1;
    key1.data = data1;

    triple_key key2;
    key2.int_key = 2;
    key2.data = data2;

    std::map<triple_key, int> myMap;
    myMap[key1] = 1;
    myMap[key2] = 2;

    cout<<myMap.size()<<endl;
}