C++ 转换如何不返回(也不抛出),只是跳过?

C++ 转换如何不返回(也不抛出),只是跳过?,c++,string,search,set,transform,C++,String,Search,Set,Transform,我想显示文件夹内容显示(没有任何文件夹系统),因此有一个std::set,其中包含std::strings,以及一些给定的指向某个目录的路径,我们希望像在普通fs中一样搜索文件夹内容。因此,有一套: set<string> demo_set; demo_set.insert("file1"); demo_set.insert("file2"); demo_set.insert("folder/file1"); demo_set.insert("folder/file2");

我想显示文件夹内容显示(没有任何文件夹系统),因此有一个
std::set
,其中包含
std::strings
,以及一些给定的指向某个目录的路径,我们希望像在普通fs中一样搜索文件夹内容。因此,有一套:

    set<string> demo_set;
demo_set.insert("file1");
demo_set.insert("file2");
demo_set.insert("folder/file1");
demo_set.insert("folder/file2");
demo_set.insert("folder/folder/file1");
demo_set.insert("folder/folder/file2");
demo_set.insert("bin/obj/Debug/CloudServerPrototype/ra.write.1.tlog");
demo_set.insert("bin/obj/Debug/CloudServerPrototype/rc.write.1.tlog");
demo_set.insert("bin/obj/Debug/vc100.idb");
demo_set.insert("bin/obj/Debug/vc100.pdb");
但我们也得到了一条空线。如何不获取它,以及如何在发现非项目时抛出错误

完整代码:

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

using namespace std;

struct get_pertinent_part
{
    const std::string given_string;

    get_pertinent_part(const std::string& s)
        :given_string(s)
    {
    }

    std::string operator()(const std::string& s)
    {
        std::string::size_type first = 0;

        if (s.find(given_string) == 0)
        {
            first = given_string.length();
        }
        else
        {
            return "";
        }

        std::string::size_type count = std::string::npos;
        std::string::size_type pos = s.find_last_of("/");
        if (pos != std::string::npos && pos > first)
        {
            count = pos + 1 - first;
        }

        return s.substr(first, count);
    }
};

void directory_listning_without_directories_demo()
{
    set<string> output;
    set<string> demo_set;

    demo_set.insert("file1");
    demo_set.insert("file2");
    demo_set.insert("folder/file1");
    demo_set.insert("folder/file2");
    demo_set.insert("folder/folder/file1");
    demo_set.insert("folder/folder/file2");
    demo_set.insert("bin/obj/Debug/CloudServerPrototype/ra.write.1.tlog");
    demo_set.insert("bin/obj/Debug/CloudServerPrototype/rc.write.1.tlog");
    demo_set.insert("bin/obj/Debug/vc100.idb");
    demo_set.insert("bin/obj/Debug/vc100.pdb");


    std::transform(demo_set.begin(),
        demo_set.end(),
        std::inserter(output, output.end()),
        get_pertinent_part("bin/obj/Debug/"));

    std::copy(output.begin(),
        output.end(),
        std::ostream_iterator<std::string>(std::cout, "\n"));
}

int main()
{
    directory_listning_without_directories_demo();
    cin.get();
    return 0;
}
#包括

#包含栅格答案。

由于没有转换,正确的方法是首先将长度非零的路径的部分结果复制到另一个容器中,然后在该新容器上运行转换

或者,如果将变换函数的结果与谓词进行比较,则可以编写类似transform_的代码。这是我未经测试的一张照片:

template <class InIt, class OutIt, class UnaryFunction, class Predicate>
void transform_if_value(InIt first, InIt last, OutIt out, UnaryFunction fn, Predicate pred)
{
    for ( ; first != last; ++ first)
    {
        auto val = fn(*first);
        if (pred(val))
            *out++ = val;
    }
}
要了解更酷的语法,请查看boost的范围适配器:

boost::copy(
    demo_set | boost::adaptors::transformed(get_pertinent_part("bin/obj/Debug/"))
             | boost::adaptors::filtered([](const std::string& s) {return !s.empty();}),
    std::inserter(output, output.begin()));

您可以使用
std::acculate
(不是从
,而是从
)将匹配项累积到输出中

std::set<string> const&
operator()(std::set<string> const& out, std::string const& candidate) const
{
    if(/* same logic to check if candidate matches */) {
        out.insert(/* insert processed/transformed path */);
    }
    return out;
}
注意
std::ref
(来自
)的用法。您不希望输出集四处移动(加上调用
std::acculate
的结果将被忽略,因此不会看到任何更改)。或者,如果不希望依赖于
std::ref
,可以使用指针


edit:heh,重温这个想法,这可能并不比使用
std::for_each
并将输出的引用传递给函子的构造函数好多少。YMMV.

如何
output.erase(“”)?嘿!我认得!为什么不先使用过滤器,然后再使用变换?
boost::copy(
    demo_set | boost::adaptors::transformed(get_pertinent_part("bin/obj/Debug/"))
             | boost::adaptors::filtered([](const std::string& s) {return !s.empty();}),
    std::inserter(output, output.begin()));
std::set<string> const&
operator()(std::set<string> const& out, std::string const& candidate) const
{
    if(/* same logic to check if candidate matches */) {
        out.insert(/* insert processed/transformed path */);
    }
    return out;
}
std::accumulate(
    demo_set.begin(), demo_set.end()
    , std::ref(output)
    , get_pertinent_path("bin/obj/Debug/") );