简体   繁体   English

为什么二分查找函数会抛出错误?

[英]Why is the binary search function throwing an error?

I am trying to search for a long long int using the binary_search function, but the function is throwing an error which I cannot interpret.我正在尝试使用 binary_search 函数搜索 long long int,但该函数抛出了一个我无法解释的错误。 Could you help me with this problem?你能帮我解决这个问题吗?

I am using code :: blocks and C ++ 11.我正在使用代码 :: 块和 C ++ 11。

Erro: ..error: no match for call to '(main()::<lambda(const Client&, const Client&)>) (const int&, Client&)'|

Code:代码:

#include <string>
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>

class Client{
public:
    int id;
    std::string name;
    long long int number;

};

int main()
{
    long long int s_num; // Edited. It was a mistake when typing here in the post.

    std::vector<Client> vCli =
    {
        { 1, "Stive", 68020899020 },
        { 2, "Anna",  13389155032 },
        { 3, "Olly",  32911233288 },
    };

    std::sort(vCli.begin(), vCli.end(), [](const Client &c1, const Client &c2) { return c1.number < c2.number; });

    for (Client c : vCli) //print test
        std::cout << c.id << " - " << c.name << " - " << c.number << std::endl;


    s_num = 13389155032; // Anna's number

    bool yesNumber = std::binary_search( vCli.begin(), vCli.end(), s_num,
                               []( const Client &c1, const Client &c2)
                                {
                                    return c1.number > c2.number;
                                } );


    yesNumber ? std::cout << "\nClient found.\n" : std::cout << "\nClient NOT found.\n" ;

    return 0;
}

From cppreference :cppreference

The types Type1 and Type2 must be such that an object of type T can be implicitly converted to both Type1 and Type2类型 Type1 和 Type2 必须是类型 T 的对象可以隐式转换为 Type1 和 Type2

In your case, T=int and int can not be implicitly converted to Client , hence the error.在您的情况下, T=intint不能隐式转换为Client ,因此出现错误。

Your lambda implements the wrong comparison.您的 lambda 实现了错误的比较。

You're asking std::binary_search to find the integer s_num within a collection of Client s, but you're only telling it how to sort Client s.您要求std::binary_searchClient的集合中查找整数s_num ,但您只是告诉它如何对Client进行排序。

It needs a function that compares Client s to long long int s.它需要一个函数来比较Client s 和long long int s。

Taking an educated guess at your requirements, that means:对您的要求进行有根据的猜测,这意味着:

bool yesNumber = std::binary_search( vCli.begin(), vCli.end(), s_num,
    [](const Client &c, const long long int val)
    {
        return c.number > val;
    }
 );

I'm actually not sure that this is sufficient, though;不过,我实际上不确定这是否足够; you may need to provide a functor that can compare Client s and long long int s in both directions (ie one with which you can swap the arguments).您可能需要提供一个可以在两个方向上比较Clientlong long int的函子(即可以交换参数的那个)。 I'll leave that as an exercise to the reader, but I can tell you that a lambda isn't going to do the job.我将把它留给读者作为练习,但我可以告诉你 lambda 不会完成这项工作。

You have sorted the vector in the opposite order as you tell it when you use std::binary_search which will make the search fail.当您使用std::binary_search ,您已经按照相反的顺序对向量进行了排序,这将使搜索失败。

And as pointed out, you use a type not implicitly convertible to a Client .正如所指出的,您使用的类型不能隐式转换为Client

Consider adding constructors:考虑添加构造函数:

Client(int Id, const std::string& Name, long long int Number) :
    id(Id), name(Name), number(Number) 
{}
Client(long long int x) : id{}, name{}, number(x) {}

And then provide the correct comparator ( < ) in the binary search:然后在二进制搜索中提供正确的比较器 ( < ):

long long int s_num = 13389155032;

bool yesNumber = std::binary_search( vCli.begin(), vCli.end(), s_num,
    [](const Client& c1, const Client c2) {
        return c1.number < c2.number;
    }
);

Alternatively, create a Client that you use for searching:或者,创建一个用于搜索的Client

Client s_num{{}, {}, 13389155032};

bool yesNumber = std::binary_search(vCli.begin(), vCli.end(), s_num,
    [](const Client& c1, const Client& c2) { 
        return c1.number < c2.number; 
    }
);

You have a few options here.你有几个选择。 One would be to define a constructor that will let you implicitly create a Client from a long long int .一种方法是定义一个构造函数,让您从long long int隐式创建Client

Another would be to define comparison between long long int and Client .另一种方法是定义long long intClient之间的比较。 The tricky point here is that you need to be prepared to handle expressions like either: long long < Client or Client < long long .这里的棘手之处在于,您需要准备好处理以下表达式: long long < ClientClient < long long There are a couple of ways you could do that.有几种方法可以做到这一点。 One would be to define a comparison class that has overloads for both directions:一种是定义一个在两个方向都有重载的比较类:

struct cmp {
    bool operator()(long long int a, Client const &b) {
        return a < b.number;
    }

    bool operator()(Client const &a, long long int b) {
        return a.number < b;
    }
};

Then pass an instance of that in the call to binary_search:然后在调用 binary_search 时传递一个实例:

bool yesNumber = std::binary_search( vCli.begin(), vCli.end(), s_num, cmp());

Another possibility would be to define a pair of getKey functions, one for a long long , and one for a Client :另一种可能性是定义一对getKey函数,一个用于long long ,一个用于Client

class Client { 
// ...

    friend long long getKey(Client const &a) { return a.number; }
};

long long getKey(long long a) { return a; }

...then write your lambda like this: ...然后像这样写你的 lambda:

[](auto const &a, auto const &b) { return getKey(a) < getKey(b); }

This way, whenever a comparison is done using the template, a type is assigned to each of a and b , and that type is used to select which overload of getKey will be called for that parameter.这样,每当使用模板进行比较时,都会为aba分配一个类型,并且该类型用于选择将为该参数调用getKey哪个重载。 Kind of roundabout, but it does work.有点迂回,但确实有效。

Yet another possibility would be to define the comparison inside of your Client class itself:另一种可能性是在您的Client类本身内部定义比较:

class Client { 
// ...

    // will be used for sorting:
    bool operator<(Client const &other) const { return number < other.number; }

    // will be used for searching:
    bool operator<(long long val) const { return number < val; }
    friend operator<(long long val, Client const &c) { return val < c.number; }
};

In this case, we don't need to specify anything about comparison when we do the sorting or searching:在这种情况下,我们在进行排序或搜索时不需要指定任何关于比较的内容:

// Each of these will automatically use Client::operator<
std::sort(vCli.begin(), vCli.end());

bool yesNumber = std::binary_search(vCli.begin(), vCli.end(), s_num);

One final point: your use of the ternary operator is a bit unusual, to say the least.最后一点:至少可以说,您对三元运算符的使用有点不寻常。 Typically you use it to yield one of two values, which is then used in an expression.通常,您使用它来生成两个值之一,然后在表达式中使用它。 If you just want to execute on of two expressions, depending on whether an expression is true or false, you'd normally use an if / else to do it.如果您只想执行两个表达式中的一个,取决于表达式是真还是假,您通常会使用if / else来执行此操作。 So the obvious choices would be either:所以显而易见的选择是:

std::cout << (yesNumber ? "\nClient found.\n" : "\nClient NOT found.\n");

...or else: ...要不然:

if (yesNumber) {
    std::cout << "\nclient found.\n";
} else {
    std::cout << "\nClient NOT found.\n";
}

Note the parentheses in the first case--they're necessary because << has higher precedence than the ternary operator.注意第一种情况下的括号——它们是必需的,因为<<比三元运算符具有更高的优先级。 Without them, the statement would be parsed as:没有它们,语句将被解析为:

(std::cout << yesNumber) ? "\nClient found.\n" : "\nClient NOT found.\n";

So it would just write yesNumber out to cout , then use the return from cout to select between the found / NOT found strings, but not put that result to any use.所以它只是写yesNumber出来cout ,然后使用从返回cout之间选择found / NOT found字符串,但结果不把任何使用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM