I am trying to write a function that would do what a cd ..
would do. Basically get the parent of the given path.
eg:
C:\ --> C:\ C:\Users\xxx --> C:\Users test1\test2\test4 --> test1\test2\ /var/etc/jpt --> /var/etc
I have tested this in windows and linux. Here are the list of comments I have.
I am declaring forward_slash
and backward_slash
so that it would work on both win and linux. One might ask, what if there are other path delimeter? For now, lets just stick to these two delimeters. If I do not find any of the two delimiters, I just return the path itself.
I loop over the dir_path
trying to find the first and second delimiter.
I have to do -1 here
int index = dir_path.size()-1;
to avoid out of bound error.If there is no delimiter found from first delimiter position (using
find_last_of
) then I return sub string from 0 to first delimiter position + 1. I have to +1 here because the for loop already moved the index by -1.If there is any thing in between the two consecutive delimiter, I just return the sub string from 0 to second delimiter position.
I have to do the
if (second_delimeter_pos == std::string::npos)
first.
The below code also has test paths.
#include <iostream>
#include <string>
#include <vector>
std::vector<std::string> generatePaths() {
std::vector<std::string> paths;
paths.emplace_back("C:\\Users\\xxxx\\\\");
paths.emplace_back("C:\\");
paths.emplace_back("C:");
paths.emplace_back("C:\\\\");
paths.emplace_back("C://");
paths.emplace_back("C:/");
paths.emplace_back("test\\test1\\tmp2");
paths.emplace_back("C:\\Users\\xxxxx\\projects\\\\\\play_ground\\\\\\");
paths.emplace_back("C:/Users/xxxxxx/projects/////play_ground////");
return paths;
}
std::string getParentDir(const std::string& dir_path) {
std::string forward_slash = "/";
std::string backward_slash = "\\";
std::string delimiter;
if (dir_path.find(forward_slash) != std::string::npos) {
delimiter = forward_slash;
}
else if (dir_path.find(backward_slash) != std::string::npos) {
delimiter = backward_slash;
}
else {
return dir_path;
}
std::string parent_path;
for (int index = dir_path.size()-1; index > 0 ; --index) {
int first_delimeter_pos = index;
size_t second_delimeter_pos = (int)dir_path.find_last_of(delimiter, first_delimeter_pos);
int diff = first_delimeter_pos - second_delimeter_pos;
if (second_delimeter_pos == std::string::npos) {
parent_path = dir_path.substr(0, first_delimeter_pos+1);
break;
}
if (diff > 1) {
parent_path = dir_path.substr(0, second_delimeter_pos);
break;
}
index -= diff;
}
return parent_path;
}
int main() {
std::vector<std::string> test_paths = generatePaths();
for (int i = 0; i < test_paths.size(); ++i) {
std::string my_dir = test_paths[i];
std::string parent_dir = getParentDir(my_dir);
std::cout << "dir = " << my_dir << " :: parent dir = " << parent_dir << std::endl;
}
}
Any suggestion, improvements and pitfall on design and algorithm is highly appreciated.