Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用std::equal_range查找字符串向量中出现的前缀范围_C++_String_Search_Range - Fatal编程技术网

C++ 使用std::equal_range查找字符串向量中出现的前缀范围

C++ 使用std::equal_range查找字符串向量中出现的前缀范围,c++,string,search,range,C++,String,Search,Range,我试图找到一个lambda,它允许std::equal_range返回一个范围,其中搜索的字符串作为前缀存在。由于措辞可能不正确,举个例子: 给定字符串向量: C:\users\andy\documents\screenshot.jpg C:\users\bob\desktop\file.txt C:\users\bob\desktop\picture.png C:\users\bob\desktop\video.mp4 C:\users\john\desktop\note.txt 我希望返

我试图找到一个lambda,它允许
std::equal_range
返回一个范围,其中搜索的字符串作为前缀存在。由于措辞可能不正确,举个例子:

给定字符串向量:

  • C:\users\andy\documents\screenshot.jpg
  • C:\users\bob\desktop\file.txt
  • C:\users\bob\desktop\picture.png
  • C:\users\bob\desktop\video.mp4
  • C:\users\john\desktop\note.txt
我希望返回的迭代器是

  • C:\users\bob\desktop\file.txt和
  • C:\users\bob\desktop\video.mp4

我该如何为
std::equal_range
编写一个比较lambda来实现这一点,或者
std::equal_range
不是适合此工作的工具?

我认为您只需要让比较器将前缀的长度与如下元素进行比较:

std::vector<std::string> v
{
    "C:/users/andy/documents/screenshot.jpg",
    "C:/users/bob/desktop/file.txt",
    "C:/users/bob/desktop/picture.png",
    "C:/users/bob/desktop/video.mp4",
    "C:/users/john/desktop/note.txt",
};

std::sort(std::begin(v), std::end(v));

std::string const prefix = "C:/users/bob/desktop/";

auto lb = std::lower_bound(std::begin(v), std::end(v), prefix);

// For the upper bound we want to view the vector's data as if
// every element was truncated to the size of the prefix.
// Then perform a normal match.
auto ub = std::upper_bound(lb, std::end(v), prefix,
[&](std::string const& s1, std::string const& s2)
{
    // compare UP TO the length of the prefix and no farther
    if(auto cmp = std::strncmp(s1.data(), s2.data(), prefix.size()))
        return cmp < 0;

    // The strings are equal to the length of the prefix so
    // behave as if they are equal. That means s1 < s2 == false
    return false;
});

// make the answer look like we used std::equal_range
// (if that's what's needed)
auto range = std::make_pair(lb, ub);

for(auto itr = range.first; itr != range.second; ++itr)
    std::cout << *itr << '\n';

为了解释为什么这样做,想象一下获取向量并对其进行排序。然后想象访问每个元素并将它们截断为前缀的长度。您将得到一个排序后的向量,其元素长度不超过前缀。在这一点上,一个简单的
std::equal_range
将满足您的要求。因此,我们需要做的就是构造一个比较器,它的行为就像容器元素被截断到前缀的长度一样,并在我们的
std::equal_range
搜索(或twin
std::lower_bound/upper_bound
搜索)中使用该比较器.

std::equal_range的四个参数重载以及comparison callable对象似乎足以完成任务。只需编写一个实现与前缀匹配的比较的比较对象。为了返回正确的比较结果,您必须小心地使用对比较对象进行编码。这似乎可行,但我不确定它是否完全正确:您可能可以使用
std::string来避免
substr
。compare
,但这对我来说更清楚。shrugI将采取比退休忍者更复杂的方法。我会将前缀字符串强制转换为一个不同的助手类型,该类型不是
std::string
。然后我可以区分这两种类型的比较函数,并在自定义比较器类中实现两个
操作符()
s,比较前缀和字符串,和字符串的前缀。那么
C:\users\bob\desktop\picture.png
为什么不应该返回它呢?使用
=
打破了严格的弱排序要求进行比较。这个答案比我能解释得更好。:)根据我对Sam Varshavchik上述评论的理解,您必须同时使用comp(元素,值)和comp(值,元素)进行比较,对吗?另外,在这里使用string::compare会更快吗?@AndrewLeFevre是的,你是对的。这比我想象的要复杂。我会再考虑一下的。@AndrewLeFevre我相信这个问题已经解决了。
C:/users/bob/desktop/file.txt
C:/users/bob/desktop/picture.png
C:/users/bob/desktop/video.mp4