缩短路径字符串功能

时间:2017-06-12 23:33:22

标签: c windows filepath c-strings

我很好奇是否有先前编写的缩短c字符串中文件路径的函数。

示例:

char* filePath1 = "\\folder1\\..\\folder1\\file.dat";
char* filePath2 = "\\folder1\\folder2\\..\\..\\folder1\\file.dat";
char* filePath3 = "\\folder1\\folder3\\..\\folder2\\..\\folder1\\file.dat";

我想知道是否有一个可以识别并减少所有这些字符串的函数

char* allFilePaths = "\\folder1\\file.dat";

我没有很高的期望,但如果有办法避免重写现有的(并且经过充分测试的)代码,我就是全力以赴!

1 个答案:

答案 0 :(得分:0)

我查看了我们的源代码并意识到我的评论非常准确地描述了实际的算法。因此,我将提供一个工作样本:

#include <iostream>
#include <string>
#include <vector>

using namespace std;

void strTok(const string &text, char delim, vector<string> &tokens)
{
  for (size_t i = 0, j, n = text.size(); i < n; i = j) {
    while (i < n && text[i] == delim) ++i;
    j = text.find(delim, i);
    if (j > n) j = n;
    tokens.push_back(text.substr(i, j - i));
  }
}

string filePathResolve(string filePath)
{
  // make paths Unix-style
  for (char &c : filePath) if (c == '\\') c = '/';
  // consider UNC paths
  const char *root = "";
  if (filePath.length() >= 2 && filePath.compare(0, 2, "//") == 0) {
    root = "//"; filePath.erase(0, 2);
  }
  // split file path into list
  vector<string> list; strTok(filePath, '/', list);
  // remove all non-functional entries (occurrences of '//' and '/.')
  for (size_t i = list.size(); i--;) {
    if (list[i].empty() || list[i] == ".") list.erase(list.begin() + i);
  }
  for (size_t i = 1; i < list.size(); ++i) {
    if (list[i] == ".." && list[i - 1] != "..") {
      list.erase(list.begin() + i - 1, list.begin() + i + 1);
      i -= 2;
    }
  }
  // rebuilt path from list
  filePath = root;
  if (list.size()) {
    filePath += list.front();
    for (size_t i = 1, n = list.size(); i < n; ++i) {
      (filePath += '/') += list[i];
    }
  }
  // done
  return filePath;
}

int main()
{
  string samples[] = {
    "\\folder1\\..\\folder1\\file.dat",
    "\\folder1\\folder2\\..\\..\\folder1\\file.dat",
    "\\folder1\\folder3\\..\\folder2\\..\\folder1\\file.dat",
    "\\.\\folder1\\..\\folder1\\file.dat",
    "folder1\\..\\folder1\\.\\file.dat"
  };
  for (string path : samples) {
    cout << "original: " << path << endl
      <<    "resolved: " << filePathResolve(path) << endl;
  }
  // done
  return 0;
}

在Windows 10(64位)上的VS2013中测试:

original: \folder1\..\folder1\file.dat
resolved: folder1/file.dat
original: \folder1\folder2\..\..\folder1\file.dat
resolved: folder1/file.dat
original: \folder1\folder3\..\folder2\..\folder1\file.dat
resolved: folder1/folder1/file.dat
original: \.\folder1\..\folder1\file.dat
resolved: folder1/file.dat
original: folder1\..\folder1\.\file.dat
resolved: folder1/file.dat

由于我们的软件是可移植的,我们更喜欢/作为目录分隔符。但是,这可以很容易地适应相反的方向,即最初每/替换\\并仅使用后者。

恕我直言,最关键的部分是UNC paths。为了我们的运气,我们的客户似乎更了解他们。至少,我从未对此抱怨(多年)。

重新阅读上面链接的维基百科文章,我意识到也提到了URL。此算法无法正确处理网址。