我只是想知道我们是否可以使用一些宏破解来更改项目中现有的 printf() 语句。
/* file.c */
printf ("%s", strerror(errno));
/* After macro processing, this line would become */
printf ("%s %s %d", strerror(errno), __FILE__, __LINE__);
我只是想知道我们是否可以使用一些宏破解来更改项目中现有的 printf() 语句。
/* file.c */
printf ("%s", strerror(errno));
/* After macro processing, this line would become */
printf ("%s %s %d", strerror(errno), __FILE__, __LINE__);
根据我的评论中的警告,您可以使用可变参数宏来做到这一点:
#define PRINTF_FL(format, ...) \
printf(format " %s %d", __VA_ARGS__, __FILE__, __LINE__)
试试这个:
#define debug(fmt, ...) printf("%s:%d: " fmt, __FILE__, __LINE__, __VA_ARGS__);
我使用 namedebug
而不是printf
,因为我认为您不应该覆盖标准函数。你可以打破一些东西。
像这样使用:
debug("This is debug no %d", 5);
要获得类似于以下内容的输出:
program.c:12: this is debug no 5
(文件:program.c
,行:12)。
重新定义printf
不使用undef
只需在头文件中定义以下printf
宏
#define printf(MESSAGE,args...) { \
const char *A[] = {MESSAGE}; \
printf("%s %d",__FILE__,__LINE__); fflush(stdout);\
if(sizeof(A) > 0) {\
printf("::"); \
printf(*A,##args); \
} else {\
printf("\n"); \
}\
}
您可以通过printf
这种方式在代码中使用新宏
printf(); // it will print only the file name and the line number
或以这种方式
printf("debug message any data %d\n", 5);
这是我的“半便士”。
// debug mode, -DEBUG
#ifdef EBUG
#define FNAME() fprintf(stderr, "\n%s (%s, line %d)\n", __func__, __FILE__, __LINE__)
#define DBG(...) do{fprintf(stderr, "%s (%s, line %d): ", __func__, __FILE__, __LINE__); \
fprintf(stderr, __VA_ARGS__); \
fprintf(stderr, "\n");} while(0)
#else
#define FNAME() do{}while(0)
#define DBG(...) do{}while(0)
#endif //EBUG
使用宏FNAME()
仅显示函数名称和文件/行,DBG(text)
以显示类似 printf 的调试消息,其中包含有关函数名称和文件/行的信息。
extern int globErr;
#define ERR(...) do{globErr=errno; _WARN(__VA_ARGS__); exit(-1);}while(0)
#define WARN(...) do{globErr=errno; _WARN(__VA_ARGS__);}while(0)
#define WARNX(...) do{globErr=0; _WARN(__VA_ARGS__);}while(0)
// functions for color output in tty & no-color in pipes
EXTERN int (*red)(const char *fmt, ...);
EXTERN int (*_WARN)(const char *fmt, ...);
EXTERN int (*green)(const char *fmt, ...);
int globErr = 0; // errno for WARN/ERR
// pointers to coloured output printf
int (*red)(const char *fmt, ...);
int (*green)(const char *fmt, ...);
int (*_WARN)(const char *fmt, ...);
/*
* format red / green messages
* name: r_pr_, g_pr_
* @param fmt ... - printf-like format
* @return number of printed symbols
*/
int r_pr_(const char *fmt, ...){
va_list ar; int i;
printf(RED);
va_start(ar, fmt);
i = vprintf(fmt, ar);
va_end(ar);
printf(OLDCOLOR);
return i;
}
int g_pr_(const char *fmt, ...){
va_list ar; int i;
printf(GREEN);
va_start(ar, fmt);
i = vprintf(fmt, ar);
va_end(ar);
printf(OLDCOLOR);
return i;
}
/*
* print red error/warning messages (if output is a tty)
* @param fmt ... - printf-like format
* @return number of printed symbols
*/
int r_WARN(const char *fmt, ...){
va_list ar; int i = 1;
fprintf(stderr, RED);
va_start(ar, fmt);
if(globErr){
errno = globErr;
vwarn(fmt, ar);
errno = 0;
globErr = 0;
}else
i = vfprintf(stderr, fmt, ar);
va_end(ar);
i++;
fprintf(stderr, OLDCOLOR "\n");
return i;
}
const char stars[] = "****************************************";
/*
* notty variants of coloured printf
* name: s_WARN, r_pr_notty
* @param fmt ... - printf-like format
* @return number of printed symbols
*/
int s_WARN(const char *fmt, ...){
va_list ar; int i;
i = fprintf(stderr, "\n%s\n", stars);
va_start(ar, fmt);
if(globErr){
errno = globErr;
vwarn(fmt, ar);
errno = 0;
globErr = 0;
}else
i = +vfprintf(stderr, fmt, ar);
va_end(ar);
i += fprintf(stderr, "\n%s\n", stars);
i += fprintf(stderr, "\n");
return i;
}
int r_pr_notty(const char *fmt, ...){
va_list ar; int i;
i = printf("\n%s\n", stars);
va_start(ar, fmt);
i += vprintf(fmt, ar);
va_end(ar);
i += printf("\n%s\n", stars);
return i;
}
if(isatty(STDOUT_FILENO)){ // make color output in tty
red = r_pr_; green = g_pr_;
}else{ // no colors in case of pipe
red = r_pr_notty; green = printf;
}
if(isatty(STDERR_FILENO)) _WARN = r_WARN;
else _WARN = s_WARN;
之后,您将能够在终端中运行时使用彩色输出,在管道中使用非彩色输出。函数red
和green
是彩色输出的类似物printf
。_WARN
宏中用于显示用户消息和字符串的函数errno
:ERR
对于错误的情况(以 结尾exit
),WARN
- 类似ERR
但没有exit
和WARNX
显示没有的消息errno
。
在宏 MYPRINT 下方定义。包括文件名、行号、函数名和\n
#define MYPRINT(str,args...) printf("%s:%d %s() "str"\n",__FILE__,__LINE__,__func__, ##args)