windows 从 C 中的路径名中提取基本路径
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6074357/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Extract base path from a pathname in C
提问by Zach Burlingame
Question
题
How do you extract the base path from pathname in C?
如何从 C 中的路径名中提取基本路径?
Are there any functions built into the C language or the C-Runtime Library to extract the base path from a pathname in C?
C 语言或 C 运行时库中是否有任何内置函数可以从 C 中的路径名中提取基本路径?
I'm asking basically the opposite of thisquestion.
我问的基本上与这个问题相反。
NOTE: I prefer a cross-platform solution, but I'm working in Windows so if there is a Windows API call that does this, I'd still like to know.
注意:我更喜欢跨平台的解决方案,但我在 Windows 中工作,所以如果有一个 Windows API 调用可以做到这一点,我仍然想知道。
Examples
例子
Input | Output
---------------------------------
C:\path\to\file -> C:\path\to\
C:\path\to\file.c -> C:\path\to\
C:\file -> C:\
.\file -> .\
.\ -> .\
\ -> \
References
参考
采纳答案by andrewdski
On Windows there is _splitpath.
在 Windows 上有_splitpath。
Example
例子
#include <Windows.h>
#include <tchar.h>
// Use your own error codes here
#define SUCCESS 0L
#define FAILURE_NULL_ARGUMENT 1L
#define FAILURE_API_CALL 2L
#define FAILURE_INSUFFICIENT_BUFFER 3L
DWORD GetBasePathFromPathName( LPCTSTR szPathName,
LPTSTR szBasePath,
DWORD dwBasePathSize )
{
TCHAR szDrive[_MAX_DRIVE] = { 0 };
TCHAR szDir[_MAX_DIR] = { 0 };
TCHAR szFname[_MAX_FNAME] = { 0 };
TCHAR szExt[_MAX_EXT] = { 0 };
size_t PathLength;
DWORD dwReturnCode;
// Parameter validation
if( szPathName == NULL || szBasePath == NULL )
{
return FAILURE_NULL_ARGUMENT;
}
// Split the path into it's components
dwReturnCode = _tsplitpath_s( szPathName, szDrive, _MAX_DRIVE, szDir, _MAX_DIR, szFname, _MAX_FNAME, szExt, _MAX_EXT );
if( dwReturnCode != 0 )
{
_ftprintf( stderr, TEXT("Error splitting path. _tsplitpath_s returned %d.\n"), dwReturnCode );
return FAILURE_API_CALL;
}
// Check that the provided buffer is large enough to store the results and a terminal null character
PathLength = _tcslen( szDrive ) + _tcslen( szDir );
if( ( PathLength + sizeof( TCHAR ) ) > dwBasePathSize )
{
_ftprintf( stderr, TEXT("Insufficient buffer. Required %d. Provided: %d\n"), PathLength, dwBasePathSize );
return FAILURE_INSUFFICIENT_BUFFER;
}
// Copy the szDrive and szDir into the provide buffer to form the basepath
if( ( dwReturnCode = _tcscpy_s( szBasePath, dwBasePathSize, szDrive ) ) != 0 )
{
_ftprintf( stderr, TEXT("Error copying string. _tcscpy_s returned %d\n"), dwReturnCode );
return FAILURE_API_CALL;
}
if( ( dwReturnCode = _tcscat_s( szBasePath, dwBasePathSize, szDir ) ) != 0 )
{
_ftprintf( stderr, TEXT("Error copying string. _tcscat_s returned %d\n"), dwReturnCode );
return FAILURE_API_CALL;
}
return SUCCESS;
}
回答by Matt__C
In Windows you can use the API call "PathRemoveFileSpec" http://msdn.microsoft.com/en-us/library/bb773748(v=vs.85).aspx
在 Windows 中,您可以使用 API 调用“PathRemoveFileSpec” http://msdn.microsoft.com/en-us/library/bb773748(v=vs.85).aspx
Cross platform solutions will not really be possible due to variations in file systems bewtween different OS's.
由于不同操作系统之间文件系统的差异,跨平台解决方案实际上是不可能的。
回答by David Heffernan
Are there any functions built into the C language or C-Runtime to extract the base path from a pathname in C?
C 语言或 C-Runtime 中是否有任何内置函数可以从 C 中的路径名中提取基本路径?
No there are not. Rules for path names are platform specific and so the standard does not cover them.
不是,没有。路径名的规则是特定于平台的,因此标准不涵盖它们。
回答by Alex K.
WinAPI (shlwapi) PathRemoveFileSpec
should do all of that with the exception of .\file
which would come back as .
WinAPI (shlwapi)PathRemoveFileSpec
应该做所有这些,除了.\file
它会作为.
回答by wong2
Just loop from back to forward until you meet the first \
只需从后向前循环,直到遇到第一个 \
回答by Zach Burlingame
I think the best solution on Windows is to use _splitpathas was suggested, to use something like basenameon Linux (more on that here).
我认为在 Windows 上最好的解决方案是按照建议使用_splitpath,在 Linux 上使用类似basename 的东西(更多关于这里)。
That said, since someone has already suggested implementing my own (and since I had already done it while I was waiting for an answer), here is what I came up with. It is not cross-platform and it does not check for /valid/ paths or expand short or relative path names.
也就是说,由于有人已经建议实施我自己的(并且因为我在等待答案时已经这样做了),这就是我想出的。它不是跨平台的,它不检查 /valid/ 路径或扩展短或相对路径名。
// Retrieves the pathpath from a pathname.
//
// Returns: SUCCESS if the basepath is present and successfully copied to the p_base_path buffer
// FAILURE_NULL_ARGUMENT if any arguments are NULL
// FAILURE_INVALID_ARGUMENTS if either buffer size is less than 1
// FAILURE_BUFFER_TOO_SMALL if the p_basepath buffer is too small
// FAILURE_INVALID_PATH if the p_pathname doesn't have a path (e.g. C:, calc.exe, ?qwa)
// FAILURE_API_CALL if there is an error from the underlying API calls
int get_base_path_from_pathname( const char* const p_pathname,
size_t pathname_size,
char* const p_basepath,
size_t basepath_size );
int get_base_path_from_pathname( const char* const p_pathname,
size_t pathname_size,
char* const p_basepath,
size_t basepath_size )
{
char* p_end_of_path;
size_t path_length;
int return_code;
// Parameter Validation
if( p_pathname == NULL || p_basepath == NULL ) { return FAILURE_NULL_ARGUMENT; }
if( pathname_size < 1 || basepath_size < 1 ) { return FAILURE_INVALID_ARGUMENTS; }
// Returns a pointer to the last occurrence of \ in p_pathname or NULL if it is not found
p_end_of_path = strrchr( p_pathname, '\' );
if( p_end_of_path == NULL )
{
// There is no path part
return FAILURE_INVALID_PATH;
}
else
{
path_length = (size_t)( p_end_of_path - p_pathname + 1 );
// Do some sanity checks on the length
if( path_length < 1 ) { return FAILURE_INVALID_PATH; }
if( ( path_length + 1 ) > basepath_size ) { return FAILURE_BUFFER_TOO_SMALL; }
// Copy the base path into the out variable
if( strncpy( p_basepath, p_pathname, path_length ) != 0 ) { return FAILURE_API_CALL; }
p_basepath[path_length] = 'char dir_ch = '\'; // set dir_ch according to platform
char str[] = "C:\path\to\file.c";
char *pch = &str[strlen(str)-1];
while(*pch != dir_ch) pch--;
pch++;
*pch = '##代码##';
';
}
return SUCCESS;
}
回答by jwodder
There is no standard C99 function for doing this. POSIX has dirname()
, but that won't help you much on Windows. It shouldn't be too hard for you to implement your own function, though; just search through the string, looking for the last occurrence of the directory separator, and discard anything after it.
没有用于执行此操作的标准 C99 函数。POSIX 有dirname()
,但这在 Windows 上对您没有多大帮助。不过,实现自己的功能对您来说应该不会太难;只需搜索字符串,查找目录分隔符的最后一次出现,然后丢弃它之后的任何内容。
回答by daalbert
Before str
is the full path and file name, after str
is just the path:
之前str
是完整路径和文件名,之后str
只是路径: