缩短路径字符串函数
我很好奇,如果有一个以前编写的函数用于缩短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";
我没有寄予厚望的功能,但如果有一种避免重写现有(并且希望经过充分测试)代码的方法,我完全赞成!
我看了一下我们的源代码,发现我的评论描述的实际算法相当不准确。因此,我将提供一个工作样本来代替:
#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。
非常感谢你提供这个!如果没有以前的功能,这就是我想要实现自己的想法。但是,@Retired Ninja指出我'_fullpath()',它将返回一个绝对路径和我想要的相对路径,所以我将使用它。 – Ryan
我注意到这也跟着退休忍者的链接。这可能是更好的解决方案(让操作系统去做)。我甚至考虑将我们的软件中的代码替换为我从中得到的样本。对于一个便携式解决方案,我想提一提[SO:安全的跨平台功能来获得规范化的路径](https://*.com/questions/7129096/safe-cross-platform-function-to-get-normalized -path)也是。 – Scheff
请注意'\ f'是一个换页。你可能打算每次使用'\\ f'。 –
你想做文本替换还是需要验证'folder2'和'folder3'是否存在?系统验证名称,但涉及更多的工作而不是纯文本替换。很可能有微软的API函数来完成这项工作。我知道我有Unix的类似代码,无论是纯文本替换还是验证 - 虽然验证代码不仅仅检查名称是否存在,它也处理符号链接,这非常有趣。 (另外请注意,由于给定的字符串都是字符串文字,因此无法在原位可靠地对其进行修改。) –
我的意思是'\\'谢谢您的更正!我想做文本替换,因为我假设所有这些文件夹都存在。你知道这些微软API函数可能是什么吗? (我假设我不会处理符号链接,但处理这些会更好) – Ryan