标准预定义宏
我明白了。
__FILE__
在C语言中显示文件的完整路径。有没有办法缩短路径并只获取文件名?我的意思是,不要显示完整路径,只显示文件名。/full/path/to/file.c
我明白了。
to/file.c
或者
file.c
__FILE__
在C语言中显示文件的完整路径。有没有办法缩短路径并只获取文件名?我的意思是,不要显示完整路径,只显示文件名。/full/path/to/file.c
to/file.c
或者
file.c
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 3.13 + gcc 4.5。使用相对路径(可能无法正常工作!)
#include <string.h>
#include <stdio.h>
const char* GetFileName(const char *path)
{
const char *name = NULL, *tmp = NULL;
if (path && *path) {
name = strrchr(path, '/');
tmp = strrchr(path, '\\');
if (tmp) {
return name && name > tmp ? name + 1 : tmp + 1;
}
}
return name ? name + 1 : path;
}
int main() {
const char *name = NULL, *path = NULL;
path = __FILE__;
name = GetFileName(path);
printf("path: %s, filename: %s\n", path, name);
path ="/tmp/device.log";
name = GetFileName(path);
printf("path: %s, filename: %s\n", path, name);
path = "C:\\Downloads\\crisis.avi";
name = GetFileName(path);
printf("path: %s, filename: %s\n", path, name);
path = "C:\\Downloads/nda.pdf";
name = GetFileName(path);
printf("path: %s, filename: %s\n", path, name);
path = "C:/Downloads\\word.doc";
name = GetFileName(path);
printf("path: %s, filename: %s\n", path, name);
path = NULL;
name = GetFileName(NULL);
printf("path: %s, filename: %s\n", path, name);
path = "";
name = GetFileName("");
printf("path: %s, filename: %s\n", path, name);
return 0;
}
path: test.c, filename: test.c
path: /tmp/device.log, filename: device.log
path: C:\Downloads\crisis.avi, filename: crisis.avi
path: C:\Downloads/nda.pdf, filename: nda.pdf
path: C:/Downloads\word.doc, filename: word.doc
path: (null), filename: (null)
path: , filename:
适用于Windows和*nix的简短、可行的答案:
#define __FILENAME__ std::max<const char*>(__FILE__,\
std::max(strrchr(__FILE__, '\\')+1, strrchr(__FILE__, '/')+1))
std::max<const char*>
而不是只用 std::max
? - chqrliestd::max
需要在头文件中包含<algorithm>
之外,我宁愿不这样做。另一个选项是通过#ifdef _WIN32
检查平台,因为__FILE__
将具有一致的分隔符字符。 - Burak#define FILENAME ({ \
const char* filename_start = __FILE__; \
const char* filename = filename_start; \
while(*filename != '\0') \
filename++; \
while((filename != filename_start) && (*(filename - 1) != '/')) \
filename--; \
filename; })
FILENAME
替代 __FILENAME__
。是的,它仍然是一个运行时的东西,但它有效。由于您正在使用GCC,因此您可以利用以下内容:
__BASE_FILE__
这个宏会展开为一个C字符串常量形式的主输入文件名。这是在预处理器或C编译器命令行中指定的源文件。
然后,通过在编译时更改源文件表示(完整路径/相对路径/基本名称),您可以控制如何显示文件名。
__FILE__
和__BASE_FILE__
,但它们都显示文件的完整路径。 - mahmoodgcc /absolute/path/to/file.c
。如果你找到了改变这种行为的方法(在SO上开另一个问题,哈哈),你就不需要在运行时修改字符串。 - ziu__BASE_FILE__
生成在命令行上指定的文件名,例如 test.c
或 /tmp/test.c
取决于你如何调用编译器。这与 __FILE__
完全相同,除非你在头文件中,在这种情况下,__FILE__
会产生当前文件的名称(例如 foo.h
),而 __BASE_FILE__
仍会产生 test.c
。 - Quuxplusone顶部的答案不够好,因为它不是编译时常量表达式。这里有一个非常简单的解决方案:
#define FILESTEM(x) \
std::string_view(x).substr(std::string_view(x).rfind(OS_PATH_SLASH) + 1, \
std::string_view(x).rfind('.') - \
std::string_view(x).rfind(OS_PATH_SLASH) - 1)
这是一个constexpr,可以在头文件中使用。
我认为这比使用strrchr函数更好。
strfnchr将搜索最后一个分隔符'/'并从__FILE__
中获取文件名,
您可以使用__FILE__NAME__
而不是__FILE__
来获取没有完整文件路径的文件名。
strrchr解决方案每次使用都会搜索文件名两次,但是此代码只需搜索1次。
即使在__FILE__
中没有分隔符'/',它也可以有效地工作。
您可以根据需要将其替换为\以使用它。
通过使用下面的strrchr源代码改进了strfnchr的源代码。我认为它比strrchr更有效。
inline const char* strfnchr(const char* s, int c) {
const char* found = s;
while (*(s++)) {
if (*s == c)
found = s;
}
if (found != s)
return found + 1;
return s;
}
#define __FILE_NAME__ strfnchr(__FILE__, '/')
#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
一个经过调整的、更加“臃肿”的版本,来自red1ynx的回答:
#define __FILENAME__ \
(strchr(__FILE__, '\\') \
? ((strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__)) \
: ((strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)))
__FILE__
包含了混合分隔符,例如 c:\abc\xyz/file.h
,那么宏就无法工作。 - insaneinvader
__FILE__
的内容。因此,不要使用gcc /full/path/to/file.c
,而是尝试cd /full/path/to; gcc file.c; cd -;
。当然,如果你依赖于gcc的当前目录来设置包含路径或输出文件位置,则需要更多的修改。编辑:gcc文档表明它是完整路径,而不是输入文件名参数,但在Cygwin上的gcc 4.5.3中,我看到的并非如此。因此,你可以在Linux上尝试一下。 - Steve Jessop__FILE__
被打印为../../../../../../../../rtems/c/src/lib/libbsp/sparc/leon2/../../shared/bootcard.c
,我想知道gcc编译文件的位置,以便该文件相对于所示的位置定位。 - Chan Kim