通过宏修改printf()以包含文件和行号信息

use*_*645 6 c

我只是想知道是否有一些我们可以使用的宏hack来改变项目中现有的printf()语句.

/* file.c */
printf ("%s", strerror(errno));

/* After macro processing, this line would become */
printf ("%s %s %d", strerror(errno), __FILE__, __LINE__);
Run Code Online (Sandbox Code Playgroud)

Som*_*ude 10

有了我的评论中的警告,你可以使用可变参数宏来做到这一点:

#define PRINTF_FL(format, ...) \
    printf(format " %s %d", __VA_ARGS__, __FILE__, __LINE__)
Run Code Online (Sandbox Code Playgroud)

  • 如果__VA_ARGS__为空,则该宏将失败.#define PRINTF_FL(format,...)\ printf(格式为"%s%d",__ VA_ARGS __,__ FILE __,_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ { }` (7认同)
  • @jianxisun尝试## __ VA_ARGS__以避免在逗号开始之前出现空__VA_ARGS_错误.应该使用gcc,如https://gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.html中所述 (7认同)

kam*_*uel 7

试试这个:

#define debug(fmt, ...) printf("%s:%d: " fmt, __FILE__, __LINE__, __VA_ARGS__);
Run Code Online (Sandbox Code Playgroud)

我使用名称debug而不是printf,因为我认为你不应该覆盖标准函数.你可以打破一些东西.

使用它像:

debug("This is debug no %d", 5);
Run Code Online (Sandbox Code Playgroud)

要获得类似于的输出:

program.c:12: this is debug no 5
Run Code Online (Sandbox Code Playgroud)

(档案:program.c,行:12).


Edd*_*_Em 5

这是我的“半便士”。

\n\n

函数名称和调试消息:

\n\n
// debug mode, -DEBUG\n#ifdef EBUG\n    #define FNAME() fprintf(stderr, "\\n%s (%s, line %d)\\n", __func__, __FILE__, __LINE__)\n    #define DBG(...) do{fprintf(stderr, "%s (%s, line %d): ", __func__, __FILE__, __LINE__); \\\n                    fprintf(stderr, __VA_ARGS__);           \\\n                    fprintf(stderr, "\\n");} while(0)\n#else\n    #define FNAME()  do{}while(0)\n    #define DBG(...) do{}while(0)\n#endif //EBUG\n
Run Code Online (Sandbox Code Playgroud)\n\n

使用宏FNAME()仅显示函数名称和文件/行,DBG(text)以显示类似 printf 的调试消息,其中包含有关函数名称和文件/行的信息。

\n\n

以及可能对彩色调试和错误/警告消息有用的东西。

\n\n

在头文件中:

\n\n
extern int globErr;\n#define ERR(...) do{globErr=errno; _WARN(__VA_ARGS__); exit(-1);}while(0)\n#define WARN(...) do{globErr=errno; _WARN(__VA_ARGS__);}while(0)\n#define WARNX(...) do{globErr=0; _WARN(__VA_ARGS__);}while(0)\n// functions for color output in tty & no-color in pipes\nEXTERN int (*red)(const char *fmt, ...);\nEXTERN int (*_WARN)(const char *fmt, ...);\nEXTERN int (*green)(const char *fmt, ...);\n
Run Code Online (Sandbox Code Playgroud)\n\n

在C文件中:

\n\n
int globErr = 0; // errno for WARN/ERR\n// pointers to coloured output printf\nint (*red)(const char *fmt, ...);\nint (*green)(const char *fmt, ...);\nint (*_WARN)(const char *fmt, ...);\n/*\n * format red / green messages\n * name: r_pr_, g_pr_\n * @param fmt ... - printf-like format\n * @return number of printed symbols\n */\nint r_pr_(const char *fmt, ...){\n    va_list ar; int i;\n    printf(RED);\n    va_start(ar, fmt);\n    i = vprintf(fmt, ar);\n    va_end(ar);\n    printf(OLDCOLOR);\n    return i;\n}\nint g_pr_(const char *fmt, ...){\n    va_list ar; int i;\n    printf(GREEN);\n    va_start(ar, fmt);\n    i = vprintf(fmt, ar);\n    va_end(ar);\n    printf(OLDCOLOR);\n    return i;\n}\n/*\n * print red error/warning messages (if output is a tty)\n * @param fmt ... - printf-like format\n * @return number of printed symbols\n */\nint r_WARN(const char *fmt, ...){\n    va_list ar; int i = 1;\n    fprintf(stderr, RED);\n    va_start(ar, fmt);\n    if(globErr){\n        errno = globErr;\n        vwarn(fmt, ar);\n        errno = 0;\n        globErr = 0;\n    }else\n        i = vfprintf(stderr, fmt, ar);\n    va_end(ar);\n    i++;\n    fprintf(stderr, OLDCOLOR "\\n");\n    return i;\n}\n\nconst char stars[] = "****************************************";\n/*\n * notty variants of coloured printf\n * name: s_WARN, r_pr_notty\n * @param fmt ... - printf-like format\n * @return number of printed symbols\n */\nint s_WARN(const char *fmt, ...){\n    va_list ar; int i;\n    i = fprintf(stderr, "\\n%s\\n", stars);\n    va_start(ar, fmt);\n    if(globErr){\n        errno = globErr;\n        vwarn(fmt, ar);\n        errno = 0;\n        globErr = 0;\n    }else\n        i = +vfprintf(stderr, fmt, ar);\n    va_end(ar);\n    i += fprintf(stderr, "\\n%s\\n", stars);\n    i += fprintf(stderr, "\\n");\n    return i;\n}\nint r_pr_notty(const char *fmt, ...){\n    va_list ar; int i;\n    i = printf("\\n%s\\n", stars);\n    va_start(ar, fmt);\n    i += vprintf(fmt, ar);\n    va_end(ar);\n    i += printf("\\n%s\\n", stars);\n    return i;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

在主函数()中:

\n\n
if(isatty(STDOUT_FILENO)){ // make color output in tty\n    red = r_pr_; green = g_pr_;\n}else{ // no colors in case of pipe\n    red = r_pr_notty; green = printf;\n}\nif(isatty(STDERR_FILENO)) _WARN = r_WARN;\nelse _WARN = s_WARN;\n
Run Code Online (Sandbox Code Playgroud)\n\n

之后,您将能够在终端中运行时使用彩色输出,在管道中运行时使用非彩色输出。函数red和与彩色输出green类似。printf宏中使用的函数_WARN显示用户消息和字符串errnoERR对于错误情况(以 结尾exit),WARN\xe2\x80\x94 类似ERR但不带exitWARNX显示不带消息errno

\n