在 printf 中使用可以扩展为整数或无值的 MACROS
Using MACROS in printf that may be expanded to an integer or no value
我正在编写一些使用以下宏的 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);
}
一个简单的解决方法是在非调试情况下#define LINE_NUMBER 0
,然后使用格式%.d
代替%d
:
SendMsg(2000, "Unable to open file %s %.d", FILE_NAME, LINE_NUMBER);
这将导致 0
不被打印 [见注 1],尽管它不会抑制任何 space 字符,因此输出仍然会有两个冗余 space消息末尾的字符。可能你不在乎这些。
如果你知道 FILE_NAME
和 LINE_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);
备注:
摘自 C11 标准,§7.21.6.1,其中记录了 *printf
格式:
…
After the %
, the following appear in sequence:
… — An optional precision that gives the minimum number of digits to appear for the d
, i
, o
, u
, x
, and X
conversions, …. The precision takes the form of a period (.
) followed either by an asterisk *
(described later) or by an optional decimal integer; if only the period is specified, the precision is taken as zero.
…
The conversion specifiers and their meanings are:
d,i
The int argument is converted to signed decimal in the style [−]dddd
. The precision specifies the minimum number of digits to appear; if the value being converted can be represented in fewer digits, it is expanded with leading zeros. The default precision is 1. The result of converting a zero value with a precision of zero is no characters.
我正在编写一些使用以下宏的 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);
}
一个简单的解决方法是在非调试情况下#define LINE_NUMBER 0
,然后使用格式%.d
代替%d
:
SendMsg(2000, "Unable to open file %s %.d", FILE_NAME, LINE_NUMBER);
这将导致 0
不被打印 [见注 1],尽管它不会抑制任何 space 字符,因此输出仍然会有两个冗余 space消息末尾的字符。可能你不在乎这些。
如果你知道 FILE_NAME
和 LINE_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);
备注:
摘自 C11 标准,§7.21.6.1,其中记录了
*printf
格式:…
After the
%
, the following appear in sequence:… — An optional precision that gives the minimum number of digits to appear for the
d
,i
,o
,u
,x
, andX
conversions, …. The precision takes the form of a period (.
) followed either by an asterisk*
(described later) or by an optional decimal integer; if only the period is specified, the precision is taken as zero.…
The conversion specifiers and their meanings are:
d,i
The int argument is converted to signed decimal in the style[−]dddd
. The precision specifies the minimum number of digits to appear; if the value being converted can be represented in fewer digits, it is expanded with leading zeros. The default precision is 1. The result of converting a zero value with a precision of zero is no characters.