我需要能够将两个不同的 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
相同(但是,路径是否不应该无关紧要'存在,它不应该改变当前的工作目录,如果 A 和 B 都是相对路径,结果应该是相对路径;我并不特别关心结果路径是否包含“..”段)。
代码需要在 Windows 7 上运行。我查看了 shell path handling functions在 Windows API 中,但它们似乎不合适:
PathAppend ,第一个路径不能是相对的:
The path supplied in pszPath cannot begin with "..\" or ".\" to produce a relative path string. If present, those periods are stripped from the output string.
PathCombine ,第一个路径不能是相对路径,也不能是 UNC 路径:
The directory path should be in the form of A:,B:, ..., Z:
(编辑:仔细检查后,该文档片段似乎可能真的属于另一个函数。提到的参数名称与方法签名中给出的参数名称不同。在事实上,正如下面第二个答案所示,PathCombine
似乎确实适用于 UNC 路径。但是,它与 PathAppend
存在同样的问题 - 因为它去除了前导 ..
来自输出路径的片段)。
- PathCchCombine和 PathAllocCombine仅适用于 Windows 8 及更高版本。
是否有任何我忽略的标准函数,或者是否有任何库可以正确处理所有情况,包括 UNC 样式路径?或者至少有一种简单的方法可以使用其他已经可用的方法来实现满足我要求的功能?
最佳答案
#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'
关于windows - 当两个路径可能是相对路径时,将路径与 Windows API 组合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33150102/