使用比较运算符将std::string作为std::map中的键

5

我想在std::map中使用std::string作为键,但是我无法正确地使用find()函数。我的代码有些复杂和庞大,所以这里提供一个小程序来演示我遇到的问题。如果有人能告诉我为什么它不能工作,我将不胜感激。

谢谢。

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

struct comparer
{
    public:
    bool operator()(const std::string x, const std::string y)
    {
         return x.compare(y)==0;
    }
};

int main(int argc, char *argv[])
{
    std::map<std::string, int, comparer> numbers;
    numbers.insert(std::pair<std::string,int>("One",1));
    numbers.insert(std::pair<std::string,int>("Two",2));
    numbers.insert(std::pair<std::string,int>("Three",3));
    numbers.insert(std::pair<std::string,int>("Four",4));
    numbers.insert(std::pair<std::string,int>("Five",5));


    std::map<std::string, int, comparer>::iterator it=numbers.find("Three");
    if(it!=numbers.end())
        printf("The number is %d\n",(*it).second);
    else
        printf("Error, the number is not found\n");
}
5个回答

6

移除你的 comparer,它就能正常工作了。问题是,你没有正确实现它。如果 x 应该被放置在 y 之前,comparer 应该返回 true。或者将 ==0 改为 <0>0(其实并没有太大区别)。


1
我将比较器更改为返回x.compare(y)<0;,它运行良好,谢谢。顺便说一下,删除比较器并没有起作用。#已解决。 - Chromex
2
不用谢,但是你对移除操作的理解有误。如果你将所有 std::map<std::string, int, comparer> 的出现替换为 std::map<std::string, int>,那么它一定会起作用。 - Michael Krelin - hacker
我在主应用程序中遇到的问题是,在添加新对之前,我必须检查映射中是否存在重复项。然而,它无法正确检测到重复项。 - Chromex
1
我在谈论这段代码,而不是你的应用程序。至于重复项,map 不允许有任何重复项,而 multimap 则可以。 - Michael Krelin - hacker
实际上这似乎并不是这种情况,当我添加两个具有相同键值的对时,遍历映射会显示两个具有相同键的条目。 - Chromex
你的意思是使用你之前的比较器吗? - Michael Krelin - hacker

3

comparer::operator() 应该返回 operator < 的值,而不是 operator == 的值。


3

std::map(以及set和它们的multi变体)强制执行严格弱序

x.compare(y) == 0;

如果字符串相等,将返回 true。比较器应该指定第一个字符串是否应该排在第二个字符串之前。要么返回 x.compare(y) < 0,要么省略比较函数。


0
自定义比较操作通常是不必要的(通常可以直接使用std::map<std::string, int>),但是当使用(不是非常短的)字符串作为键并传递一个字符串常量(char*常量)(或std::string_view或任何其他可以与std::string进行简单比较而无需转换为std::string的类型)给contains()find()时,可以进行一些优化,详见https://www.cppstories.com/2021/heterogeneous-access-cpp20/
(另外,您的comparer::operator()也可以接受const字符串引用,以避免在那里进行复制: bool operator()(const std::string& x, const std::string& y) const...)

-1

这应该可以工作:

#include <stdio.h>
#include <string>
#include <map>
struct comparer
{
    public:
    bool operator()(const std::string x, const std::string y) const
    {
         return x.compare(y)==0;
    }
};

int main(int argc, char *argv[])
{
    std::map<std::string, int, comparer> numbers;
    numbers.insert(std::pair<std::string,int>("One",1));
    numbers.insert(std::pair<std::string,int>("Two",2));
    numbers.insert(std::pair<std::string,int>("Three",3));
    numbers.insert(std::pair<std::string,int>("Four",4));
    numbers.insert(std::pair<std::string,int>("Five",5));


    std::map<std::string, int, comparer>::iterator it=numbers.find("Three");
    if(it!=numbers.end())
        printf("The number is %d\n",(*it).second);
    else
        printf("Error, the number is not found\n");
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接