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 WhoIsMySpecialParent(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 thatstd::setuses. 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. Thestd::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 astd::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 anupper_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 yourstd::set. So for instance: