首页 > 代码库 > 精简Linux文件路径

精简Linux文件路径

精简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文件路径