2017-06-12 13 views
0

ファイルパスを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'と' folder3'が存在することを検証する必要がありますか?システムは名前を検証しますが、それはプレーンなテキスト置換よりも多くの作業になります。この作業を行うためのMicrosoft API関数がある可能性は非常に高いです。私は、コードのUNIX類似物を持っていることを知っています。プレーンテキストの置換と検証の両方がありますが、検証コードは名前が存在するかどうかだけではなく、シンボリックリンクも処理します。 (指定された文字列はすべて文字列リテラルなので、その場でそれらを確実に変更することはできません)。 –

+0

私は '\\'訂正をお願いします!これらのフォルダがすべて存在すると仮定しているので、テキスト置換を行いたいと思います。これらのMicrosoft APIの機能は何ですか? (私はシンボリックリンクを扱わないことを前提としていますが、それらを処理する方がより良いでしょう) – Ryan

答えて

0

私のソースコードを見て、私のコメントが実際のアルゴリズムを正確に説明していないことに気付きました。そのため、私が代わりに働いてサンプルを提供します。当社のソフトウェアは、移植を意図していると

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 

は、我々はディレクトリの区切りとして/を好む

#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でテスト。しかしながら、これは逆の方向に作用するように容易に適合させることができ、即ち最初に/\\で置き換え、後者を排他的に使用する。

IMHO、最も重要な部分はUNC pathsです。私たちの運については、顧客はそれをもっと少なく理解しているようです。少なくとも、私はこれについて(何年も)何の苦情も受けていませんでした。

上記のリンク先のWikipediaの記事を読んで、URLも記載されていることに気付きました。 このアルゴリズムではURLが正しく処理されません。

+0

これを提供してくれてありがとう!以前の機能がなければ、私は自分自身を実装するだろうと想像したことです。しかし、@Retired Ninjaは '_fullpath()'を指しています。絶対パスと相対パスの両方を返すので、代わりにこれを使用します。 – Ryan

+0

退職した忍者のリンクにもこのことが気付きました。これはおそらくより良い解決策です(OSにそれをさせる)。私はそこからサンプルを派生させた私たちのソフトウェアのコードを置き換えることさえ考えています。ポータブルソリューションについては、[SO:安全なクロスプラットフォーム関数を使って正規化されたパスを取得する](https://stackoverflow.com/questions/7129096/safe-cross-platform-function-to-get-normalized) -path)も同様です。 – Scheff

関連する問題