缩短路径字符串函数

问题描述:

我很好奇,如果有一个以前编写的函数用于缩短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

请注意'\ f'是一个换页。你可能打算每次使用'\\ f'。 –

+1

你想做文本替换还是需要验证'folder2'和'fol​​der3'是否存在?系统验证名称,但涉及更多的工作而不是纯文本替换。很可能有微软的API函数来完成这项工作。我知道我有Unix的类似代码,无论是纯文本替换还是验证 - 虽然验证代码不仅仅检查名称是否存在,它也处理符号链接,这非常有趣。 (另外请注意,由于给定的字符串都是字符串文字,因此无法在原位可靠地对其进行修改。) –

+0

我的意思是'\\'谢谢您的更正!我想做文本替换,因为我假设所有这些文件夹都存在。你知道这些微软API函数可能是什么吗? (我假设我不会处理符号链接,但处理这些会更好) – Ryan

我看了一下我们的源代码,发现我的评论描述的实际算法相当不准确。因此,我将提供一个工作样本来代替:

#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; 
} 

测试在VS2013在Windows 10(64位):

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也被提及。 该算法无法正确处理URL。

+0

非常感谢你提供这个!如果没有以前的功能,这就是我想要实现自己的想法。但是,@Retired Ninja指出我'_fullpath()',它将返回一个绝对路径和我想要的相对路径,所以我将使用它。 – Ryan

+0

我注意到这也跟着退休忍者的链接。这可能是更好的解决方案(让操作系统去做)。我甚至考虑将我们的软件中的代码替换为我从中得到的样本。对于一个便携式解决方案,我想提一提[SO:安全的跨平台功能来获得规范化的路径](https://*.com/questions/7129096/safe-cross-platform-function-to-get-normalized -path)也是。 – Scheff