STL <set>搜索

时间:2016-03-20 16:46:23

标签: c++ stl

我想存储唯一的字符串并检测重复项。 我以为我会使用STL set容器,但是我的字符串是char * 所以我做set<char *>但是当我想搜索一个项目时我该怎么做?因为它是比较指针值而不是值。

3 个答案:

答案 0 :(得分:2)

首选(大幅度)是存储std::string

理论上,第二种选择是在构造集合时提供比较对象(或函数)。但至少在我看来,这通常更多的是痛苦而不是它的价值。如果你真的想这样做,代码看起来像这样:

auto cmp = [](char const *a, char const *b) { return strcmp(a, b) < 0; };

std::set<char *, decltype(cmp)> more(cmp);

more.insert("Third");
more.insert("First");
more.insert("Second");

这留下了我认为更实用的 1 选择来定义你自己的小字符串类,它支持你真正需要的操作,这是一般顺序:

#include <iostream>
#include <cstring>

class my_str {
    char const *data;
public:
    my_str(char const *data) : data(data) {}

    bool operator<(my_str const &other) const {
        return strcmp(data, other.data) < 0;
    }

    operator char const *() const { return data; }

    friend std::ostream &operator<<(std::ostream &os, my_str const &m) {
        return os << m.data;
    }
};

注意:这只会存储构造时传递给它的指针。它不会尝试存储数据的副本(如std::string那样),因此您可以确保传递给它的每个字符串在对象的生命周期内保持有效。这对于字符串文字来说是微不足道的,但对于其他几乎所有东西来说都是站不住脚的(当然,这是std::string工作原理的主要原因。)

要使用此功能,您可以执行以下操作:

#include <set>

int main() {
    std::set<my_str> strings{"xyz", "abc"};

    for (auto const &s : strings)
        std::cout << s << "\n";
}

但请注意上面的警告:这个字符串类太过于简单,无法真正使用。更糟糕的是,如果你错误地使用它(特别是在一个小测试中),很可能会立即看到你的使用问题。

但是,我可能会因为编写C ++ 98/03的时间比编写更现代的C ++要长得多。 功能

答案 1 :(得分:2)

每当你能提供合理的定义时,就可以使用

std::set;一个元素小于另一个元素&#34;。为了使此功能尽可能灵活,它有一个模板参数,默认为std::less<T>,表示要使用的小于比较功能。

换句话说, std::set<char*>std::set<char*, std::less<char*>> [*] 的缩写。

std::less<T>是一种有点&#34;魔法&#34;仿函数,因为它允许人们安全地比较指针并获得比较的定义结果(令人惊讶的是,如果直接通过<比较指针,情况并非如此)。

但这对你没有帮助。您根本不想比较指针,您想要取消引用指针并检查它们指向的值。

为了做到这一点,只需使用比较参数实例化std::set模板即可。基于指针的std::strcmp C函数可帮助您执行实际比较。这是一个例子:

struct CStringPointerComparison
{
    bool operator()(char const* lhs, char const* rhs) const
    {
        return std::strcmp(lhs, rhs) < 0;
    }
};

std::set<char*, CStringPointerComparison> my_set;

[*]这本身就是std::set<char*, std::less<char*>, std::allocator<char*>>的缩写,但分配器在这里并不重要。

答案 2 :(得分:0)

我强烈建议您使用std::set<std::string>std::set<char *>是一组指针

要查找目标对象,您需要取消引用指针。所以,我建议(如果你把它作为一组指针):

  1. 通过集合迭代:
  2. 在每次迭代中,使用strcmpset项与您的项进行比较 目标C样式字符串。
  3. 如果使用迭代器,则需要在将迭代器传递给strcmp函数之前取消引用迭代器。

    注意:如果您使用std::set<std::string>,则可以使用find算法或集合中的方法。无需解除引用。

    简化您的生活,使用std::string