开发者

How do I manage directories' paths with std::map or set?

开发者 https://www.devze.com 2023-03-22 01:34 出处:网络
I\'d like to use stl::set to put some directory paths. The set has some special directory paths which I put.

I'd like to use stl::set to put some directory paths. The set has some special directory paths which I put. And I should find the special parent of some input paths.

There is the code. And I commented some points.

set<wstring> special_directories;

void WhoIs开发者_开发百科MySpecialParent(const wstring& f)
{
    set<wstring>::const_iterator it;
    it = special_directories.upper_bound(f);

    if (it == special_directories.begin())
    {
        printf("There isn't any special parent.");
        return;
    }

    --it;
    wprintf(L"The special parent is <%s>\n", it->c_str());
}

int _tmain(int argc, _TCHAR* argv[])
{
    // These are special directories which I will manage.
    // "/home" and "/home/benjamin" are not included in the special directories.
    // If I want to make "/home" as special directory,
    // I have to add "/home" in the set.
    special_directories.insert(L"/");
    special_directories.insert(L"/bin");
    special_directories.insert(L"/etc");
    special_directories.insert(L"/home/benjamin/documents");
    special_directories.insert(L"/var");
    special_directories.insert(L"/var/log");

    WhoIsMySpecialParent(L"/bin/ls"); // Okay. It prints /bin
    WhoIsMySpecialParent(L"/var/log/aaaa"); // Okay. It prints /var/log
    WhoIsMySpecialParent(L"/var/apache2"); // Okay. It prints /var

    WhoIsMySpecialParent(L"/bz");
    // Wrong. It prints "/bin". It should print "/"

    WhoIsMySpecialParent(L"/home/benjamin");
    // Wrong. It prints "/etc", It should print "/"

    return 0;
}

I thought this can be handled with upper_bound. But I might be wrong.

How do you think? Should I give up to use std::set?

If you were me, how would you solve this problem? any idea please.


Using std::set<T>::upper_bound() simply finds the lexicographical sorted sorted index that is the mathematical upper bound in the tree data-structure that std::set uses. In this case "/etc" was the upper bound to "home/benjamin" since if you count through the alphabet, "home/benjamin" will come before "home/benjamin/documents" and right after "/etc". Therefore in the sorted tree, you would find that "/etc" was the least upper bound for your search parameter "home/benjamin". If you wanted to get "/" as the result, you would have to find the greatest upper bound in the data-structure, not the least upper bound. By "greatest", I'm talking in the mathematical sense, where a sorted tree will create a topological sort that has N number of upper-bounds for a given search string, if those upper bounds exist. The std::set<T>::upper_bound() method finds the least of these upper-bounds, meaning it finds the first possible upper-bound from a lexicographical sort (since that is the method it's using to sort a std::string). With your "/home/benjamin" case, you are looking for the greatest upper-bound that includes a root directory that is a "special" directory. But unfortunately applying that criteria to your other cases will break some of them (i.e., it will always return "/"). That means you are going to have to create a custom version of an upper_bound() type function for your needs that does not work strictly by a lexicographical sorting of the elements to find the upper-bound. In fact I wouldn't even use an upper_bound search.

A better approach would be to use std::string::find_last_of(), and use that to parse your directories by the / character. Doing so, you can parse and basically "peel" back the directory paths until you find a perfect match in your std::set. So for instance:

void WhoIsMySpecialParent(const wstring& f)
{
    wstring temp = f;
    while (temp.size())
    {
        temp = temp.substr(0, temp.find_last_of(L"/"));

        set<wstring>::const_iterator it;

        //setup a special case for the root directory
        if (temp.size())
            it = special_directories.find(temp);
        else
            it = special_directories.find(L"/");

        if (it != special_directories.end())
        {
            wprintf(L"The special parent is <%s>\n", it->c_str());
            return;
        }
    }

    printf("There isn't any special parent.");
    return;
}
0

精彩评论

暂无评论...
验证码 换一张
取 消