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;
}
精彩评论