C语言中可用的标准预定义宏__FILE__显示文件的完整路径。有办法缩短这条路吗?我的意思是
/full/path/to/file.c
我看到
to/file.c
or
file.c
C语言中可用的标准预定义宏__FILE__显示文件的完整路径。有办法缩短这条路吗?我的意思是
/full/path/to/file.c
我看到
to/file.c
or
file.c
当前回答
#include <algorithm>
#include <string>
using namespace std;
string f( __FILE__ );
f = string( (find(f.rbegin(), f.rend(), '/')+1).base() + 1, f.end() );
// searches for the '/' from the back, transfers the reverse iterator
// into a forward iterator and constructs a new sting with both
其他回答
在MSVC中,将FILENAME宏作为FILENAME=%(FILENAME)%(扩展名)添加到c++项目的预处理器定义中。恐怕这完全是一个编译器杀手。它在某种程度上打破了并行构建。
GCC 12将提供GNU C扩展宏__FILE_NAME__来获取编译文件的基名。
请参阅GCC文档,其中已经包含了这个宏:GCC -common_predefined_macros
GCC线程:Bug 42579 - [PATCH]支持获取文件basename
我做了一个宏__FILENAME__,以避免每次都切割完整路径。问题是将结果文件名保存在cppp -local变量中。
这可以通过在.h文件中定义一个静态全局变量来轻松实现。 这个定义在每个.cpp文件中给出了独立的变量。 为了成为一个多线程证明,值得让变量也是线程本地(TLS)。
一个变量存储文件名(压缩后)。另一个保存了__FILE__给出的非剪切值。h文件:
static __declspec( thread ) const char* fileAndThreadLocal_strFilePath = NULL;
static __declspec( thread ) const char* fileAndThreadLocal_strFileName = NULL;
宏本身使用所有逻辑调用方法:
#define __FILENAME__ \
GetSourceFileName(__FILE__, fileAndThreadLocal_strFilePath, fileAndThreadLocal_strFileName)
函数是这样实现的:
const char* GetSourceFileName(const char* strFilePath,
const char*& rstrFilePathHolder,
const char*& rstrFileNameHolder)
{
if(strFilePath != rstrFilePathHolder)
{
//
// This if works in 2 cases:
// - when first time called in the cpp (ordinary case) or
// - when the macro __FILENAME__ is used in both h and cpp files
// and so the method is consequentially called
// once with strFilePath == "UserPath/HeaderFileThatUsesMyMACRO.h" and
// once with strFilePath == "UserPath/CPPFileThatUsesMyMACRO.cpp"
//
rstrFileNameHolder = removePath(strFilePath);
rstrFilePathHolder = strFilePath;
}
return rstrFileNameHolder;
}
removePath()可以以不同的方式实现,但最简单快捷的方法似乎是使用strrchr:
const char* removePath(const char* path)
{
const char* pDelimeter = strrchr (path, '\\');
if (pDelimeter)
path = pDelimeter+1;
pDelimeter = strrchr (path, '/');
if (pDelimeter)
path = pDelimeter+1;
return path;
}
至少对于gcc, __FILE__的值是编译器命令行中指定的文件路径。如果你像这样编译file.c:
gcc -c /full/path/to/file.c
__FILE__将展开为“/full/path/to/file.c”。如果你这样做:
cd /full/path/to
gcc -c file.c
那么__FILE__将展开为“file.c”。
这可能是实际的,也可能不是。
C标准不要求这种行为。关于__FILE__,它只是将其扩展为“当前源文件的假定名称(字符串字面值)”。
另一种方法是使用#line指令。它覆盖当前行号,也可选择覆盖源文件名。如果你想覆盖文件名但保留行号,使用__LINE__宏。
例如,你可以把它添加到文件的顶部。c:
#line __LINE__ "file.c"
唯一的问题是它将指定的行号赋给下一行,而#line的第一个参数必须是一个数字序列,因此您不能执行类似的操作
#line (__LINE__-1) "file.c" // This is invalid
确保#line指令中的文件名与文件的实际名称匹配作为练习。
至少对于gcc来说,这也会影响诊断消息中报告的文件名。
一个简短的,适用于Windows和*nix的答案:
#define __FILENAME__ std::max<const char*>(__FILE__,\
std::max(strrchr(__FILE__, '\\')+1, strrchr(__FILE__, '/')+1))