如何从C中的路径名中提取基本路径?
C语言或C运行时库中是否内置了从C中的路径名中提取基本路径的功能?
我问this问题基本上是相反的。
注意:我更喜欢跨平台解决方案,但我在Windows中工作,所以如果有一个Windows API调用,我仍然想知道。
Input | Output
---------------------------------
C:\path\to\file -> C:\path\to\
C:\path\to\file.c -> C:\path\to\
C:\file -> C:\
.\file -> .\
.\ -> .\
\ -> \
答案 0 :(得分:6)
在Windows上有_splitpath。
#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;
}
答案 1 :(得分:4)
C语言或C-Runtime中是否内置了从C中的路径名中提取基本路径的函数?
不,没有。路径名称的规则是特定于平台的,因此标准不包括它们。
答案 2 :(得分:4)
在Windows中,您可以使用API调用“PathRemoveFileSpec”http://msdn.microsoft.com/en-us/library/bb773748(v=vs.85).aspx
由于不同操作系统之间的文件系统存在差异,因此无法实现跨平台解决方案。
答案 3 :(得分:2)
WinAPI(shlwapi)PathRemoveFileSpec
应该执行所有操作,但.\file
除外.
答案 4 :(得分:1)
只需从后向前循环,直到遇到第一个\
答案 5 :(得分:1)
这样做没有标准的C99功能。 POSIX有dirname()
,但这对Windows没什么帮助。但是,实现自己的功能应该不会太难;只需搜索字符串,查找最后一次出现的目录分隔符,然后丢弃它后面的任何内容。
答案 6 :(得分:1)
我认为Windows上最好的解决方案是按照建议使用_splitpath,在Linux上使用basename之类的东西(更多关于here)。
那就是说,因为有人已经建议实施我自己的(因为我在等待答案的时候已经完成了),这就是我想出来的。它不是跨平台的,它不检查/ valid / paths或扩展短路径名或相对路径名。
// 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] = '\0';
}
return SUCCESS;
}
答案 7 :(得分:0)
在str
之前是完整路径和文件名,str
之后只是路径:
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 = '\0';