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
当前回答
如果您最终在本页上寻找一种方法,以从您正在交付的二进制文件中删除指向丑陋构建位置的绝对源路径,那么下面可能适合您的需要。
尽管这并没有得到作者所希望的答案,因为它假设使用CMake,但它已经非常接近了。很遗憾之前没有人提到这一点,因为这可以节省我很多时间。
OPTION(CMAKE_USE_RELATIVE_PATHS "If true, cmake will use relative paths" ON)
将上述变量设置为ON将生成如下格式的构建命令:
cd /ugly/absolute/path/to/project/build/src &&
gcc <.. other flags ..> -c ../../src/path/to/source.c
因此,__FILE__宏将解析为../../src/path/to/source.c
CMake文档
但是要注意文档页上的警告:
使用相对路径(可能不起作用!)
它不能保证在所有情况下都能工作,但在我的CMake 3.13 + gcc 4.5中工作
其他回答
只是希望改进一下FILE宏:
#定义文件(strrchr(__FILE__, '/') ?strrchr __FILE __, '/') + 1: strrchr __FILE __, '\\') ?strrchr(__FILE__, '\\') + 1: __FILE__)
这捕获/和\,像Czarek Tomczak要求的,这在我的混合环境中工作得很好。
使用basename()函数,或者,如果是在Windows上,使用_splitpath()。
#include <libgen.h>
#define PRINTFILE() { char buf[] = __FILE__; printf("Filename: %s\n", basename(buf)); }
还可以在shell中尝试man 3 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;
}
Try
#include <string.h>
#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
对于Windows,使用“\\”而不是“/”。
red1ynx的答案经过调整,甚至更加“臃肿”:
#define __FILENAME__ \
(strchr(__FILE__, '\\') \
? ((strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__)) \
: ((strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)))
如果我们发现反斜杠,我们就分反斜杠。否则,拆分为正斜杠。很简单。
几乎任何替代方案都会更简洁(在我看来,c++ constexpr确实是这里的黄金标准)。然而,如果你正在使用一些__BASE_FILE__不可用的编译器,这可能是有帮助的。