6

プロジェクト内の既存の printf() ステートメントを変更するために、使用できるマクロ ハックがあるかどうか疑問に思っていました。

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

/* After macro processing, this line would become */
printf ("%s %s %d", strerror(errno), __FILE__, __LINE__);
4

5 に答える 5

12

私のコメントの警告で、可変引数マクロを使用してそれを行うことができます:

#define PRINTF_FL(format, ...) \
    printf(format " %s %d", __VA_ARGS__, __FILE__, __LINE__)
于 2013-03-21T14:17:58.780 に答える
8

これを試して:

#define debug(fmt, ...) printf("%s:%d: " fmt, __FILE__, __LINE__, __VA_ARGS__);

標準関数をオーバーライドする必要はないと思うので、debug代わりにname を使用しました。printfあなたは何かを壊すことができます。

これを次のように使用します。

debug("This is debug no %d", 5);

次のような出力を取得するには:

program.c:12: this is debug no 5

(ファイル: program.c、行: 12)。

于 2013-03-21T14:15:04.117 に答える
4

そして、これが私の「ハーフペニー」です。

関数名とデバッグメッセージ:

// 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, ...);

Cファイルの場合:

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;
}

main()で:

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関数で、次のユーザーメッセージと文字列を表示します:エラーの場合(で終わる)、—の類似物ですが、なしでメッセージを表示します。_WARNerrnoERRexitWARNERRexitWARNXerrno

于 2013-03-21T14:51:10.213 に答える
4

再定義するには、ヘッダーファイルで次のマクロを定義するだけでprintf使用しないでくださいundefprintf

#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);
于 2013-03-21T14:18:37.660 に答える