【问题标题】:Troubling adding to a map麻烦添加到地图
【发布时间】:2014-04-13 00:58:05
【问题描述】:

我正在尝试使用自定义比较器构建地图,但是,我无法弄清楚的事情出错了,无法将项目添加到地图(具体来说,只能添加第一项)

struct byKey
{
    bool operator () ( const Key &key1, const Key &key2) const {
        return key1.keytoInt() < key2.keytoInt();
    }
};

其中 Key 类有一个私有 char[5],比如

char[0]=1, char[1]=2, char[3]=13, char[4]=20, char[5]=28

有一个匹配去确保char digit[5]中的所有字符(小于32)并且可以转换为字符。如char=0,它会搜索一个表,找到一个字符喜欢A

我使用Key中的一个方法将其转换为int,然后与int进行比较

int Key ::  keytoInt() const{
    int sum;
    sum=atoi(digit);
    return sum;
}

我用键和值都作为键类型构建了一个映射表,但是,当尝试对其进行测试时,我无法将项目添加到表中,我不确定哪里出错了。

没有编译错误,但是,从逻辑上讲,即使我在地图中插入了 3 次,map.size() 显示只有一个

map<Key,Key,byKey> firstmap;  
map<Key,Key>::iterator it;
firstmap.insert(pair<Key,Key>(base,stepguess));
firstmap.insert(pair<Key,Key>(stepguess,base));
firstmap[stepguess]=base;
cout << "wait";
cout << "mymap.size() is " << firstmap.size() << '\n';

【问题讨论】:

  • @avarookie 请用文字描述函数 keytoInt 必须做什么。
  • '我不知道哪里出了问题。'到底哪里出了问题?编译错误,意外行为?请编辑您的问题以提供此信息。
  • 你为什么不为你的 Key 类重载 operator
  • 看来关键特征必须重新考虑一遍。到目前为止描述的行为意味着使用std::string 作为映射键。无需再调用atoistruct byKey 就会消失。另请记住,地图可以通过在地图实例声明的第三个参数中使用less &lt;T&gt;greater&lt;T&gt; 以升序或降序排序。

标签: c++ map


【解决方案1】:

每当您将密钥转换为整数进行比较时,最好直接比较字段。在这种特殊情况下,请考虑使用memcmp,例如:

bool operator()(const Key& lhs, const Key& rhs) {
    return memcmp(lhs.digit, rhs.digit, sizeof(Key::digit)) < 0;
}

atoi 在这种情况下将始终返回 0,除非您的值是有效的 ASCII 数字(它们不是)。

【讨论】:

    【解决方案2】:

    所以,这就是我所知道的:

    class Key {
        public:
            int keyToInt() const {
                return atoi(digit);
            }
    
        private:
            char digit[5];
    };
    

    您还建议,有一个示例 Key 具有:

    Key k;
    k.digit = {1, 2, 13, 20, 28};
    

    在这种情况下,您有 2 个错误:

    1. digit 不是空终止的。所以调用atoi() 是未定义的行为。
    2. digit 中的 ascii 字符不是数字,因此您将得到无用的结果。

    我们还可以构建一个完整的测试用例,表明std::map 是正常的。

    #include <map>
    #include <cassert>
    #include <cstring>
    
    class Key {
        public:
            Key() {
                strncpy(m_digit, "0", 5);
                assert(m_digit[4] == '\0');
            }
    
            Key(const char *digit) {
                strncpy(m_digit, digit, 5);
                assert(m_digit[4] == '\0');
            }
    
            int keyToInt() const {
                return atoi(m_digit);
            }
    
        private:
            char m_digit[5];
    };
    
    struct byKey {
        bool operator () ( Key const & key1, Key const & key2) const {
            return key1.keyToInt() < key2.keyToInt();
        }
    };
    
    int main() {
        std::map<Key, Key, byKey> myMap;
    
        Key a("123");
        Key b("234");
    
        myMap[a] = b;
        myMap[b] = a;
    
        assert(myMap.size() == 2);
    }
    

    【讨论】:

    • 对于错误2,有一个匹配可以确保char digit[5]中的所有字符(小于32)并且可以转换为字符。如char = 0,它将搜索一张桌子,找一个像A这样的字符,不麻烦
    • 如果没有您可以向我们展示的兼容测试用例,那么您将很难诊断出您的问题。我添加了一个测试用例的示例。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-05
    • 2013-03-28
    • 1970-01-01
    • 1970-01-01
    • 2020-11-02
    相关资源
    最近更新 更多