在printf中使用MACROS,可以扩展为整数或无值

时间:2015-12-03 13:54:23

标签: c++ macros printf variadic-functions

我正在编写一些使用以下宏的C ++代码:

#if(PRINT_DEBUG_SYMBOLS)
    #define FILE_NAME __FILE__
    #define LINE_NUMBER __LINE__
#else
    #define FILE_NAME ""
    #define LINE_NUMBER 

我以下列方式使用这些宏:

SendMsg(2000, "Unable to open file %s %d", FILE_NAME, LINE_NUMBER);

正如您所见,FILE_NAME已扩展为文件名或基于PRINT_DEBUG SYMBOLS的空字符串。我想要与LINE__NUMBER类似的行为。它应该根据PRINT_DEBUG_SYMBOLS打印行号或没有号码。但是对于整数,没有像空字符串那样的等价物,所以当PRINT_DEBUG_SYMBOLS = 0时,我得到一些随机整数。我该如何解决这个问题?

这是SendMsg()的定义。我不具备修改此功能的灵活性。

void SendMsg(int code, char* Msg, ...)
{
    char buffer[256];
    va_list args;
    va_start(args, Msg);
    vsprintf(buffer, Msg, args);
    ostringstream line;
    line<<code<<buffer;
    printf("%s", line.str);
}

1 个答案:

答案 0 :(得分:1)

一个简单的解决方案是在非调试案例中#define LINE_NUMBER 0,然后使用格式%.d代替%d

SendMsg(2000, "Unable to open file %s %.d", FILE_NAME, LINE_NUMBER);

这将导致0无法打印[请参阅注释1],虽然它不会抑制任何空格字符,因此输出仍将在消息末尾有两个冗余空格字符。可能你不关心那个。

如果您知道FILE_NAMELINE_NUMBER都是宏(或类似__LINE__的伪宏)并且LINE_NUMBER是一个字面数字,那么您可以将字符串化字符串连接以生成单个字段:

#define STR_(x) #x
#define STR(x) STR_(x)
#define FILE_LINE FILE_NAME " " STR_(LINE_NUMBER)

SendMsg(2000, "Unable to open file %s", FILE_LINE);

或者您可能更复杂并提供格式和值宏:

// FILE_NAME and LINE_NUMBER need to be defined at some point
#if(PRINT_DEBUG_SYMBOLS)
    #define FILE_LINE FILE_NAME, LINE_NUMBER
    #define FL_FMT "%s:%d"
#else
    #define FILE_LINE ""
    #define FL_FMT "%s"
#endif

// ...
SendMsg(2000, "Unable to open file " FL_FMT, FILE_LINE);

注意:

  1. 摘录自C11标准§7.21.6.1,该文件记录*printf格式:

      

    ...

         

    %之后,以下顺序出现:

         

    ... - 一个可选的精度,为dioux以及转化X,....精度采用句点(.)的形式,后跟星号*(稍后描述)或可选的十进制整数;如果只指定了句点,则精度为零。

         

    ...

         

    转换说明符及其含义为:

         

    d,i int参数在样式[−]dddd中转换为带符号的十进制数。精度指定要显示的最小位数;如果转换的值可以用更少的数字表示,则使用前导零进行扩展。默认精度为1.转换零值且精度为零的结果不是字符。