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
当前回答
下面是一个适用于Linux(路径'/')和Windows('\'和'/'混合)的可移植函数。使用gcc, clang和vs编译。
#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:
其他回答
I think this is better than using strrchr function. strfnchr will search last delemeter '/' and get filename from __FILE__ and you can use __FILE__NAME__ instead __FILE__ for get file name without full file path. strrchr solution searching filename twice per use. but this code is just 1 time search. And it works effectively even if there is no seperater '/' in __FILE__. You can use it by replacing it with \ as needed. The source code of strfnchr was improved by using the source code of strrchr below. I think it will work more effectively than strrchr. https://code.woboq.org/userspace/glibc/string/strrchr.c.html
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__, '/')
上面的答案不够好,因为它不是一个编译时const表达式 这里有一个非常简单的解决方案:
#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,可以在头文件中使用。
对于Visual Studio,您可以使用/d1trimfile选项。
你可能想把它设置为/d1trimfile:"$(SolutionDir)\":
注意:“”前面加了\的解释:
要转义第一个($(SolutionDir)以反斜杠结束),否则将转义引号。你需要等量的反斜杠 在引用之前。
使用basename()函数,或者,如果是在Windows上,使用_splitpath()。
#include <libgen.h>
#define PRINTFILE() { char buf[] = __FILE__; printf("Filename: %s\n", basename(buf)); }
还可以在shell中尝试man 3 basename。
下面是一个解决方案,适用于没有字符串库的环境(Linux内核,嵌入式系统等):
#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__。是的,它仍然是一个运行时的东西,但它是有效的。