当两个路径可能是相对路径时,将路径与Windows API组合在一起

时间:2015-10-15 13:37:38

标签: windows winapi

我需要能够将两个不同的Windows路径(两者都可能是相对的)组合到一个路径中(通过将第二个路径应用为第一个路径的扩展)。无论文件系统上是否存在任何路径都无关紧要。例子:

C:\abc + def -> C:\abc\def
C:\abc + ..\def -> C:\def
\\server\share + def -> \\server\share\def
..\some\path\abc + ..\def -> ..\some\path\def
..\some\path + ..\..\..\def -> ..\..\def

理想情况下,它还应解决与驱动器相关的绝对问题。路径(即以单个反斜杠开头的路径)到给定驱动器上的相应路径:

C:\abc + \def -> C:\def

最后,如果它通过返回绝对路径来处理第二条路径绝对的情况会很好:

C:\abc + D:\def -> D:\def

另一种表达方式是:

我想要一个以路径为参数的函数' A'和路径' B'输出' C'应该像我先用A调用SetCurrentDirectory然后用B调用然后调用GetCurrentDirectory一样(但是,如果路径不存在则无关紧要,它应该在no point更改当前工作目录,如果A和B都是相对路径,结果应该是相对路径;我不特别在意结果路径是否包含' ..' segment)。

代码需要在Windows 7上运行。我已经查看了Windows API中的shell path handling functions,但它们看起来并不合适:

    对于PathAppend
  • ,第一条路径不能是相对的:

      

    pszPath中提供的路径不能以" .. \"开头。或"。\"至   产生一个相对路径字符串。如果存在,则剥离这些期间   来自输出字符串。

  • 对于PathCombine
  • ,第一条路径不能是相对路径,也不能是UNC路径:

      

    目录路径应采用A:,B:,...,Z:

    的形式

编辑:仔细观察,这段文档似乎真的属于另一个函数。提到的参数名称与方法签名中给出的参数名称不同。事实上,如下面的第二个答案所示,PathCombine似乎确实与UNC路径一起使用。但是,它具有与PathAppend相同的问题 - 因为它会从前导..段中删除输出路径)。

是否有任何我忽略的标准功能,或者是否有任何库可以正确处理所有情况,包括UNC风格的路径?或者至少有一种简单的方法来实现一个能够使用已经可用的其他功能满足我的要求的功能吗?

2 个答案:

答案 0 :(得分:0)

#include <stdio.h>
#include <stdlib.h>

#ifndef MAX_PATH
#define MAX_PATH 260
#endif

char *rootFolder(char *folder);

int IsFullPath(const char *p){
    if(p && *p){
        if(((*p>='A') && (*p<='Z')) ||((*p>='a') && (*p<='z'))){
            return  p[1]==':';
        }
        return *p=='\\' & p[1]=='\\';
    }
    return 0;
}
/*_______________________________________________________
*/
char *FolderUp(char *path,int deep){



    path=rootFolder(path);
    if(!*path) return path;

    int i=strlen(path);

    char *p=path;
    if(path[i-1]=='\\') path--;

    while(i &&(deep>0)){
         i--;
        if(path[i]=='\\'){
            p=&path[i+1];
            deep--;
        }
    }
    return  p;

}
/*_________________________________________________________________
*/
char *NextFolder(char *path){
    while(*path){
        path++;
        if(*path=='\\'){
            path++;
            break;
        }
    }
    return path;
}
/*_________________________________________________________________
*/
char *rootFolder(char *folder){
    char *p;
    if((*folder=='\\') && (folder[1]=='\\')){
        return NextFolder(&folder[2]);
    }

    if(*folder && folder[1]==':' && folder[2]=='\\')
        return &folder[3];
    return folder;
}


int chdir(/*IN_OUT*/char *curDir,const /*IN*/char *newDir){ 

    int deep=0,i;
    const char *p=newDir,*tmp;


    if(!newDir ||!*newDir ) return 0;

    if(IsFullPath(newDir)){
        strcpy(curDir,newDir);
        return 1;
    }

    if(*newDir=='\\'){
        tmp=rootFolder(curDir);
        if(*tmp!='\\') tmp--;
        strcpy(tmp,newDir);
        return 1;
    }

    /**/

    while(*p && (p[0]=='.' && p[1]=='.')) {
        if(p[2]!='\\') {
            deep=0;
            break;
        }
        p+=3;
        deep++;
    }
    if(deep){
        tmp=FolderUp(curDir,deep);
        if(tmp[-1]!='\\') p--;
        strcpy(tmp,p);
        return 1;
    }

    i=strlen(curDir);
    if(i && curDir[i-1]!='\\'){
        curDir[i]='\\';
        curDir[i+1]=0;
    }
    strcat(curDir,newDir);
    return 1;
    /**/
}

void DoTest(char *curDir,char *newDir){
    char path[MAX_PATH];
    strcpy(path,curDir);

    if(chdir(path,newDir))
        printf("'%s' + '%s' -> %'%s'\n",curDir,newDir,path);
    else
        printf("Error: an unhandled error occured\n");
    return ;

}
int main(){

    DoTest("C:\\abc","def");
    DoTest("C:\\abc","..\\def");
    printf("\n");

    DoTest("C:\\abc\\","def");
    DoTest("C:\\abc\\","..\\def");
    printf("\n");

    DoTest("\\\\server\\share","def");
    DoTest("\\\\server\\share","..\\def");
    printf("\n");

    DoTest("\\\\server\\share\\","def");
    DoTest("\\\\server\\share\\","..\\def");
    printf("\n");

    DoTest("\\\\server","def");
    DoTest("\\\\server","..\\def");
    printf("\n");

    DoTest("\\\\server\\","def");
    DoTest("\\\\server\\","..\\def");
    printf("\n");

    DoTest("c:\\Folder","\\\\server\\share");
    DoTest("\\\\server\\share","c:\\Folder");
    printf("\n");

    DoTest("..\\Folder\\sub folder","..\\sibling");
    printf("\n");
    return 0;
}

这是输出:

'C:\abc' + 'def' -> 'C:\abc\def'
'C:\abc' + '..\def' -> 'C:\def'

'C:\abc\' + 'def' -> 'C:\abc\def'
'C:\abc\' + '..\def' -> 'C:\def'

'\\server\share' + 'def' -> '\\server\share\def'
'\\server\share' + '..\def' -> '\\server\def'

'\\server\share\' + 'def' -> '\\server\share\def'
'\\server\share\' + '..\def' -> '\\server\def'

'\\server' + 'def' -> '\\server\def'
'\\server' + '..\def' -> '\\server\def'

'\\server\' + 'def' -> '\\server\def'
'\\server\' + '..\def' -> '\\server\def'

'c:\Folder' + '\\server\share' -> '\\server\share'
'\\server\share' + 'c:\Folder' -> 'c:\Folder'

'..\Folder\sub folder' + '..\sibling' -> '..\Folder\sibling'

答案 1 :(得分:0)

这使用WINAPI函数。

'C:\abc' + 'def' -> 'C:\abc\def'
'C:\abc' + '..\def' -> 'C:\def'

'C:\abc\' + 'def' -> 'C:\abc\def'
'C:\abc\' + '..\def' -> 'C:\def'

'\\server\share' + 'def' -> '\\server\share\def'
'\\server\share' + '..\def' -> '\\server\def'

'\\server\share\' + 'def' -> '\\server\share\def'
'\\server\share\' + '..\def' -> '\\server\def'

'\\server' + 'def' -> '\\server\def'
'\\server' + '..\def' -> '\\def'

'\\server\' + 'def' -> '\\server\def'
'\\server\' + '..\def' -> '\\def'

'c:\Folder' + '\\server\share' -> '\\server\share'
'\\server\share' + 'c:\Folder' -> 'c:\Folder'

'c:\Folder' + '\share' -> 'c:\share'
'\\server\share' + '\Folder' -> '\\server\share\Folder'

'..\Folder\sub folder' + '..\sibling' -> 'Folder\sibling'

这是输出

{{1}}