精简Linux的文件路径:

  1. ..回退的功能
  2. .留在当前文件夹
  3. //仅仅保留一个/
  4. abc/..要返回.
  5. 报错
  6. 删除最后一个/
主要思路: 用栈记录路径的起始位置,讨论/后的不同情况就可以:

#include <iostream>
#include <map>
#include <algorithm>
#include <limits.h>
#include <assert.h>
#include <stack>
using namespace std;
int selectK(int num[], int k, int l, int r) { assert(k <= (r - l + 1) && k >= 1);
int mid = (l + r) / 2, i = l, j = r;
while (i <= j) {
while (num[i] < num[mid]) {
++i;
}
while (num[j] > num[mid]) {
--j;
}
if (i <= j) {
swap(num[i],num[j]);
++i,--j;
}
}
if (k == i - l)
return num[i - 1];
else if (k < i - l)
return selectK(num, k, l, i -1);
else if (k == j + 1 - l)
return num[j + 1];
else
return selectK(num, k - (j - l + 2), j + 2, r);
}
void pathcompress(char* str) {
int i = 0, j = 0; char prev = '\0';
stack<int> offset;
offset.push(0);
while(str[i]) {
if (prev == '/') {
if (str[i] == '.' && (str[i + 1] == '/' || str[i + 1] == '\0')) {
prev = str[i + 1], i += 1;
}
else if (str[i] == '.' && str[i + 1] == '.' && (str[i + 2] == '/' || str[i + 2] == '\0')) {
i += 2;
if (offset.empty()) {
cout << "error" << endl;
return;
}
j = offset.top();
offset.pop();
if (offset.empty() && str[0] == '/') {
cout << "error" << endl;
return;
}
}
else if (str[i] == '/') {
prev = str[i++];
}
else {
offset.push(j);
prev = str[i];
str[j++] = str[i++];
}
}
else {
prev = str[i];
str[j++] = str[i++];
}
}
if (j >=3 && str[j - 1] == '/' && str[j-2] == '/')
str[j-2] = '\0';
else if (j >= 2 && str[j - 1] == '/')
str[j-1] = '\0';
else
str[j] = '\0';
if (str[0] == '\0'){
str[0] = '.';
str[1] = '\0';
} } int main()
{
int num[] = {3,2,1,4,5};
int res1 = selectK(num, 1, 0, 4);
int res2 = selectK(num, 2, 0, 4);
int res3 = selectK(num, 3, 0, 4);
int res4 = selectK(num, 4, 0, 4);
int res5 = selectK(num, 5, 0, 4);
// int res6 = selectK(num, 6, 0, 4); //char str[] = "////";
char str[] = "/.abc/xxx./abc/bacd/.././bcd/fsgs/../../../x/y/z/../../../..";
pathcompress(str);
printf("%s\n",str); return 0;
}

BUT this isn't right, For example: char str[] = "../../../etc/xyz/../abc"; You couldn't print error here. The right solution is:


You must distinguish the differences with the headers ../ and dir/

#include <iostream>
#include <map>
#include <algorithm>
#include <limits.h>
#include <assert.h>
#include <stack>
using namespace std;
int selectK(int num[], int k, int l, int r) { assert(k <= (r - l + 1) && k >= 1);
int mid = (l + r) / 2, i = l, j = r;
while (i <= j) {
while (num[i] < num[mid]) {
++i;
}
while (num[j] > num[mid]) {
--j;
}
if (i <= j) {
swap(num[i],num[j]);
++i,--j;
}
}
if (k == i - l)
return num[i - 1];
else if (k < i - l)
return selectK(num, k, l, i -1);
else if (k == j + 1 - l)
return num[j + 1];
else
return selectK(num, k - (j - l + 2), j + 2, r);
} void pathcompress2(char* str) {
stack<int> path;
int i = 0, j = 0;
bool isRoot = (str[0] == '/');
char prev = '\0';
int len = strlen(str); if (!(len >= 3 && str[0] == '.' && str[1] == '.' && str[2] == '/'))
path.push(0);
while(str[i]) {
if (prev == '/') {
if (str[i] == '.' && (str[i+1] == '/' || str[i+1] == '\0')) {
prev = '/'; if (str[i+1] == '\0') {
str[j] = '\0';
break;
}
i+=2;
}
else if (str[i] == '.' && str[i+1] == '.' && (str[i+2] == '/' || str[i+2] == '\0')) {
if (path.empty()) {
str[j++] = str[i];
str[j++] = str[i+1];
str[j++] = str[i+2];
prev = '/'; if (str[i+2] == '\0') {
str[j] = '\0';
break;
}
i+=3;
}
else {
j = path.top();
path.pop(); if (path.empty() && isRoot) { // The case : cd /..
printf("Error\n");
return;
}
if (str[i+2] == '\0') {
str[j] = '\0';
break;
}
prev = '/';
i += 3;
}
}
else if (str[i] == '/')
prev = str[i++];
else {
prev = str[i];
path.push(j);
str[j++] = str[i++];
}
}
else {
prev = str[i];
str[j++] = str[i++];
}
} if (j >= 2 && str[j - 1] == '/')
str[j-1] = '\0';
else
str[j] = '\0';
if (str[0] == '\0'){
str[0] = '.';
str[1] = '\0';
} } int main()
{
int num[] = {3,2,1,4,5};
int res1 = selectK(num, 1, 0, 4);
int res2 = selectK(num, 2, 0, 4);
int res3 = selectK(num, 3, 0, 4);
int res4 = selectK(num, 4, 0, 4);
int res5 = selectK(num, 5, 0, 4);
// int res6 = selectK(num, 6, 0, 4); char str[] = "/.abc/xxx./abc/bacd/.././bcd/fsgs/../../../x/y/z/../../../../.././././xda";
//char str[] = "asdf/.abc/xxx./abc/bacd/.././bcd/fsgs/../../../x/y/z/../../../../../../.././../.././././";
//char str[] = "/xyz/./bcd/fsgs/../../../x/y/z/../../../..";
//char str[] = "../../../etc/xyz/../abc/////////////////////////////.asdf/../../../../"; pathcompress2(str);
printf("%s\n",str); return 0;
}

The concise version is :


void pathcompress2(char* str) {
stack<int> path;
int i = 0, j = 0, len = strlen(str);
bool isRoot = (str[0] == '/');
char prev = '\0';
if (!(len >= 3 && str[0] == '.' && str[1] == '.' && (str[2] == '/' || str[2] == '\0'))
path.push(0);
while(str[i]) {
if (prev == '/') {
if (str[i] == '.' && (str[i+1] == '/' || str[i+1] == '\0')) {
prev = '/';
if (str[i+1] == '\0') {
str[j] = '\0';
break;
}
i+=2;
}
else if (str[i] == '.' && str[i+1] == '.' && (str[i+2] == '/' || str[i+2] == '\0')) {
if (path.empty()) {
str[j++] = str[i],str[j++] = str[i+1],str[j++] = str[i+2],prev = '/';
}
else {
j = path.top();
path.pop();
if (path.empty() && isRoot) { // The case : cd /..
printf("Error\n");
return;
}
}
if (str[i+2] == '\0') {
str[j] = '\0';
break;
}
prev = '/',i += 3;
}
else if (str[i] == '/')
prev = str[i++];
else {
prev = str[i],path.push(j),str[j++] = str[i++];
}
}
else {
prev = str[i],str[j++] = str[i++];
}
}
if (j >= 2 && str[j - 1] == '/')
str[j-1] = '\0';
else
str[j] = '\0';
if (str[0] == '\0'){
str[0] = '.',str[1] = '\0';
}
}

最新文章

  1. jquery的live转on的办法
  2. 第一次尝试编写java
  3. iOS-协议与代理&lt;转&gt;
  4. 复习课程jdbc:使用配置文件properties进行连接数据库,数据库存取图片,批处理,时间戳,事物回滚等等
  5. 【Unity3D基础教程】给初学者看的Unity教程(六):理解Unity的新GUI系统(UGUI)
  6. Java中文乱码解决
  7. 从源码看Android中sqlite是怎么读DB的(转)
  8. android static达到Service与Activity于Handler沟通
  9. java第二课,java基础2
  10. vue-cli ——解决多次复用含有Echarts图表组件的问题
  11. 【SSL】OV、DV和EV证书的区别
  12. ESP-手机--双向通信模式
  13. Activiti动态设置办理人扩展
  14. mysql主从复制常见故障解决
  15. MyBatis中实现多表查询
  16. 背水一战 Windows 10 (40) - 控件(导航类): AppBar, CommandBar
  17. js获取图片的原始尺寸
  18. 关于README的内容
  19. 系统管理员都要知道的 30 个 Linux 系统监控工具
  20. 简单的mongo小工具 python

热门文章

  1. Code Coverage and Unit Test in SonarQube
  2. 2-1 Restful中HTTP协议介绍
  3. linux 标准输出和后台运行
  4. kubernetes系列
  5. [Offer收割]编程练习赛42
  6. vue-cli简介(中文翻译)
  7. html行级元素和块级元素以及css转换
  8. less常用方法
  9. JDK和Cglib实现动态代理实例及优缺点分析
  10. RedHat/CentOS 大文件拆分及合并与md5验证