Given an absolute path for a file (Unix-style), simplify it.
For example,
path = "/home/"
, => "/home"
path = "/a/./b/../../c/"
, => "/c"
Corner Cases:
- Did you consider the case where path =
"/../"
?
In this case, you should return"/"
. - Another corner case is the path might contain multiple slashes
'/'
together, such as"/home//foo/"
.
In this case, you should ignore redundant slashes and return"/home/foo"
.
Accept: 3ms
思路:将 path 按 "/" 进行 split,然后放入 stack中:
- 遇到 ".." 则从stack中弹出一个元素(注意stack为空情况);
- 遇到 "." 或者空("//" 的case),忽略;
- 其他情况将 字符串压入stack中。
然后从 bottom到top输出stack。
struct Part {
char *s;
size_t len;
struct Part *next;
};
struct Part* split(char* path) {
struct Part *head = NULL;
struct Part *p = NULL;
++path;
char *s = strchr(path, '/');
while (s != NULL) {
if (head == NULL) {
head = malloc(sizeof(struct Part));
p = head;
} else {
p->next = malloc(sizeof(struct Part));
p = p->next;
}
p->s = path;
p->len = s - path;
p->next = NULL;
path = s + 1;
s = strchr(path, '/');
}
if (head == NULL) {
head = malloc(sizeof(struct Part));
p = head;
} else {
p->next = malloc(sizeof(struct Part));
p = p->next;
}
p->s = path;
p->len = strlen(path);
p->next = NULL;
return head;
}
char* simplifyPath(char* path) {
struct Part* head = split(path);
const int MAX_PATH = 1000;
struct Part* stack[MAX_PATH];
int n = 0;
while (head != NULL) {
struct Part* next = head->next;
if (head->len == 2 && strncmp(head->s, "..", 2) == 0) {
if (n > 0) {
free(stack[--n]);
}
free(head);
} else if (head->len == 0 || (head->len == 1 && head->s[0] == '.')) {
free(head);
} else {
stack[n++] = head;
}
head = next;
}
char* rst = malloc(strlen(path) + 1);
char* p = rst;
for (int i = 0; i < n; ++i) {
*p++ = '/';
memcpy(p, stack[i]->s, stack[i]->len);
p += stack[i]->len;
free(stack[i]);
}
if (p == rst) {
*p++ = '/';
*p = '\0';
} else {
*p = '\0';
}
return rst;
}