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

其他回答

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__, '/')

使用basename()函数,或者,如果是在Windows上,使用_splitpath()。

#include <libgen.h>

#define PRINTFILE() { char buf[] = __FILE__; printf("Filename:  %s\n", basename(buf)); }

还可以在shell中尝试man 3 basename。

对@red1ynx提议的轻微变化将创建以下宏:

#define SET_THIS_FILE_NAME() \
    static const char* const THIS_FILE_NAME = \
        strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__;

在每一个。c(pp)文件中添加:

SET_THIS_FILE_NAME();

然后你可以引用THIS_FILE_NAME而不是__FILE__:

printf("%s\n", THIS_FILE_NAME);

这意味着每个.c(pp)文件执行一次构造,而不是每次引用宏时都执行。

它仅限于从.c(pp)文件中使用,不能从头文件中使用。

下面是一个解决方案,适用于没有字符串库的环境(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__。是的,它仍然是一个运行时的东西,但它是有效的。

c++ 11 msvc2015u3、gcc5.4 clang3.8.0 模板<typename T, size_t S> (const T (& str)[S], size_t i = S - 1) { 返回(str[i] == '/' || str[i] == '\\') ?I + 1:(I > 0 ?Get_file_name_offset (str, I - 1): 0); } template <typename T> (T (& str)[1]) { 返回0; }

'

    int main()
    {
         printf("%s\n", &__FILE__[get_file_name_offset(__FILE__)]);
    }

代码在以下情况下产生编译时偏移量:

gcc:至少gcc6.1 + -O1 Msvc:将结果放入constexpr变量: constexpr auto file = &__FILE__[get_file_name_offset(__FILE__)]; printf (" % s \ n ",文件); Clang:坚持不编译时计算

有一个技巧可以强制所有3个编译器进行编译时间计算,即使在调试配置中禁用优化:

    namespace utility {

        template <typename T, T v>
        struct const_expr_value
        {
            static constexpr const T value = v;
        };

    }

    #define UTILITY_CONST_EXPR_VALUE(exp) ::utility::const_expr_value<decltype(exp), exp>::value

    int main()
    {
         printf("%s\n", &__FILE__[UTILITY_CONST_EXPR_VALUE(get_file_name_offset(__FILE__))]);
    }

https://godbolt.org/z/u6s8j3