set<string>:如何列出不以给定字符串开头并以`/`结尾的字符串?

Posted

技术标签:

【中文标题】set<string>:如何列出不以给定字符串开头并以`/`结尾的字符串?【英文标题】:set<string>: how to list not strings starting with given string and ending with `/`? 【发布时间】:2011-11-02 09:59:00 【问题描述】:

例如我们在我们的集合中:

 bin/obj/Debug/CloudServerPrototype/ra.write.1.tlog 
 bin/obj/Debug/CloudServerPrototype/rc.write.1.tlog 
 bin/obj/Debug/vc100.idb 
 bin/obj/Debug/vc100.pdb 

所以这就是我根据grate answer 尝试的:

#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() + 1;
        

        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;

这个输出:

CloudServerPrototype/
file1
file2
folder/
folder/folder/
vc100.idb
vc100.pdb

我们得到了bin/obj/Debug/string。我们要cout:

vc100.idb 
vc100.pdb 
CloudServerPrototype/

这样的事情怎么办?

【问题讨论】:

看起来string::find()string::substr() 的组合可以解决问题。 @Kerrek 还有很多其他事情。 set 迭代、string 操作或cout 的哪一部分尝试此操作时,您遇到了困难? @Kerrek SB:std::string::find_last_of() 在这里也很有用。 @Johnsyweb:鉴于 OP 已经发布了关于一组文件名的十几个问题,也许我们可以开始拼凑这个难题。就像 Torchwood Miracle Day,只是 Lauren Ambrose 是一个 STL 容器。 【参考方案1】:

目前尚不清楚您卡在问题的哪一部分,所以这里是您的入门。

获取“给定字符串”和最终“/”(如果存在)之间的字符串部分:

std::string get_pertinent_part(const std::string& s)

    std::string::size_type first = 0;
    if (s.find(given_string) == 0)
    
        first = given_string.length() + 1;
    

    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);

要将这些部分插入新集合 (output) 以保证唯一性,您可以使用以下方法:

std::transform(your_set.begin(),
               your_set.end(),
               std::inserter(output, output.end()),
               get_pertinent_part);

您可能希望将given_string 传递给get_pertinent_part(),在这种情况下您需要将其转换为仿函数:

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;

        //
        // ...same code as before...
        //

        return s.substr(first, count);
    
;

你可以这样称呼它:

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

输出新的set

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

将结果排序留作练习。

【讨论】:

所以...我终于不想尝试了...但它有点不起作用=(感谢您的回答...但是您能做得更好吗? @Kabumbus: "这有点行不通=(" 因为你改变了你的问题和改变了输入参数。看起来你现在想过滤掉given_string 的输入不存在。这是微不足道的,我会留给你。【参考方案2】:

我能想到的最简单的方法是:使用标准 C 函数:

char * string1 = "bin/obj/Debug"
char * string2 = "bin/obj/Debug/CloudServerPrototype/rc.write.1.tlog"
char result[64];
// the above code is just to bring the strings into this example

char * position = strstr(string1, string2);
int substringLength;
if(position != NULL)
    position += strlen(string2);
    substringLength = strchr(position, '/') - position;
    strncpy(result, position, substringLength);
else
    strcpy(result, string1); // this case is for when your first string is not found


cout << result;

发生的第一件事是在我们正在分析的字符串中找到子字符串string1,即string2。一旦我们找到了起点,并假设它在那里,我们使用指针算术将该子字符串的长度添加到该起点,然后通过从终点位置减去起点位置来找到结果字符串的长度,找到与strchr(position, '/')。然后我们简单地将该子字符串复制到缓冲区中,然后用 cout 打印。

我确信std::string 有一种很好的方法,但我会把它留给任何可以更好地解释 c++ 字符串的人,我从来没有设法适应它们,哈哈

【讨论】:

OP 使用的是 set&lt;string&gt; 而不是 set&lt;char*&gt; 不需要“通过使用古老的 [C] 代码发布答案来拖钓 [C++]”。 @Johnsyweb - 我实际上是在发布此内容后添加了该简历,一半人知道它永远不会被阅读。我看错了一半!此外,当我阅读标题时,我正在寻找他们是否想要问题正文中的 std::string 或 cstring 版本,人们会期待这样的事情。我很遗憾地忽略了它。【参考方案3】:

您想要做什么的快速示例。

String.find():http://www.cplusplus.com/reference/string/string/find/

String.subStr(): http://www.cplusplus.com/reference/string/string/substr/

string str = "bin/obj/Debug/vc100.pdb";
    string checkString ("bin/obj/Debug");

     // Check if string starts with the check string
     if (str.find(checkString) == 0)
      // Check if last letter if a "/"
      if(str.substr(str.length()-1,1) == "/")
        // Output strating at the end of the check string and for
        // the differnce in the strings.
        cout << str.substr(checkString.length(), (str.length() - checkString.length()) ) << endl;
      
     

【讨论】:

以上是关于set<string>:如何列出不以给定字符串开头并以`/`结尾的字符串?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Vector<String> 在以多线程样式访问它时不以同步方式运行 [重复]

列表选择为 Set<String> - 如何使用?

如何在 openapi-generator 中定义 List<Map<Integer, Set<String>>> 属性?

如何在Set的Assertj Collection中验证

如何在LinearLayout中使用edittext在set按钮下列出视图

Java:如何保存SET 作为HashMap中的值?