精简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';
}
}

精简Linux文件路径的更多相关文章

  1. Linux 文件路径包含特殊字符的处理方式

    文件路径包含特殊字符的处理方式 1)只用转义符 \ 2)使用双引号 mv /home/".Sent Items"/ /home/".&XfJT0ZABkK5O9g ...

  2. 截取linux文件存储路径方法

    1.截取linux文件存储路径方法 package com.tydic.eshop.action.freemarker; public class dddd { public static void ...

  3. 【linux下查看文件路径--jdk】

    1.which java 首先输入命令行,查看结果: [root@localhost ~]# which java /usr/bin/java PS:which Java是无法定位到Java的安装路径 ...

  4. Linux下如何查看tomcat是否安装、启动、文件路径、进程ID

    Linux下如何查看tomcat是否安装.启动.文件路径.进程ID 在Linux系统下,Tomcat使用命令的操作! 检测是否有安装了Tomcat: rpm -qa|grep tomcat 查看Tom ...

  5. linux sed命令查询结果前后批量追加内容(html文件批量修改css,js等文件路径)

    1.需求:linux使用shell命令查询结果前后批量追加内容 例如:我需要在当前目录下所有的css文件路径前追加域名 我想的是用sed替换去实现,鲍哥的思路是用for循环 1.1方法1:鲍哥的for ...

  6. 关于File.separator 文件路径:window与linux下路径问题(“No such file or diretory ”异常解决方案)

    最近有个在页面上传Excel文件至服务器指定目录并进行数据校验.最后入库及进行进一步处理的应用情境,我写好代码在模拟环境下测试,完全没问题:但客户试用的时候,却老是报告“No such file or ...

  7. linux whereis-查找二进制程序、代码等相关文件路径

    推荐:更多Linux 文件查找和比较 命令关注:linux命令大全 whereis命令用来定位指令的二进制程序.源代码文件和man手册页等相关文件的路径. whereis命令只能用于程序名的搜索,而且 ...

  8. Linux库文件路径的添加

    库文件在连接(静态库和共享库)和运行(仅限于使用共享库的程序)时被使用,其搜索路径是在系统中进行设置的.一般 Linux 系统把 /lib 和 /usr/lib 两个目录作为默认的库搜索路径,所以使用 ...

  9. linux 头文件路径

    linux 头文件路径 /usr/include

随机推荐

  1. php建立简单的用户留言系统

    php建立简单的用户留言系统 样例 addMsg.php--添加留言页面 doAction.php--响应添加留言页面 . viewMsg.php--显示留言页面 目录结构 addMsg.php--添 ...

  2. CodeForces 651C

    Description Watchmen are in a danger and Doctor Manhattan together with his friend Daniel Dreiberg s ...

  3. Node.js:事件循环

    ylbtech-Node.js:事件循环 1.返回顶部 1. Node.js 事件循环 Node.js 是单进程单线程应用程序,但是通过事件和回调支持并发,所以性能非常高. Node.js 的每一个 ...

  4. hammer教程

    一.前言 移动端框架当前还处在初级阶段,但相对于移动端的应用来说已经有很长时间了.虽然暂时还没有PC端开发的需求量大,但移动端的Web必然是一种趋势,在接触移动端脚本的过程中,最开始想到的是juqer ...

  5. SQL注入原理解析以及举例1

    sql注入是指web应用程序对用户输入数据的合法性没有判断,导致攻击者可以构造不同的sql语句来实现对数据库的操作. sql注入漏洞产生满足条件: 1:用户能够控制数据的输入. 2:原本需要执行的代码 ...

  6. Map初始化

    转载至:http://blog.csdn.net/dujianxiong/article/details/54849079 第一种方法:static块初始化 public class Demo{ pr ...

  7. Solr.NET快速入门(五)【聚合统计,分组查询】

    聚合统计 属性 说明 Min 最小值 Max 最大值 Sum 总和 Count 记录数,也就是多少行记录 Missing 结果集中,有多少条记录是空值 SumOfSquares 平方和(x1^2 + ...

  8. Monad 系列

    本系列是在学习Monad时在网上找到的一个老外的博客,作者是MikeHadlow,地址是mikehadlow.blogspot.com,  可惜国内访问不了.这个系列对Monad讲解的浅显易懂,而且有 ...

  9. javascript实现双击网页自动滚动,单击滚动停止

    当网页中有长篇文章时,浏览起来就比较吃劲了,想想一边忙着拖动滚动条,一边忙着浏览,确实挺累人的.为了客人能够轻松的浏览,我们可以使用script代码实现网页的自动滚屏,当双击网页的时候,网页将会自动向 ...

  10. 06--C语言数学函数

    在使用C语言数学函数时候,应该在该源文件中使用以下命令行: #include <math.h> 或 #include "math.h",这里的<>跟&quo ...