2016-06-21 97 views
1

是否存在一个标准的C/C++函数,给定一个printf格式字符串,它返回它所期望的参数个数?例如: -确定printf参数的数量

num_printf_args("%d %s") == 2; 
num_printf_args("%.1f%%") == 1; 
num_printf_args("%*d") == 2; 

只是计算的%数格式的字符串将是第一个近似值,这在第一个例子中的作品,但显然不是在第二个和第三个。

我知道gcc可以做到这一点,因为在编译时它会报告实际传递给printf的参数数量(以及它们的类型)与格式字符串不匹配。

+0

没有这样的功能,在ISO/IEC 9899:1999(语言标准)。不完全确定:2011年,但我不这么认为。这是由GCC实施的扩展。 – DevSolar

+1

没有关于参数类型的信息,它为什么会有用? –

+0

这不是语言的一部分,而是一个特定的gcc扩展。请参阅[gcc的函数属性]中的'format'(https://gcc.gnu.org/onlinedocs/gcc-3.2/gcc/Function-Attributes.html)。 – usr2564301

回答

5

没有标准的功能来做到这一点。

然而,它很容易实现。

通过计算%之后的数字%。对于计数为%的每一个加上1,紧接着是*

当计算运行的%字符时,不允许重叠。因此“%%% d”应该产生值1(而不是0,当然不是23)。

编辑 - 文本的下方添加以下评论来自user694733

这将足以满足沿着你给的三个例子行格式字符串。但是,正如user694733在评论中指出的那样,这不是全部。

一般而言,格式说明符跟在原型%[flags][width][.precision][length]specifier之后。上面的方法是一个起点,并且将适用于格式字符串没有flags,可能*width说明符,*precision说明符,并忽略lengthspecifier字段。所有这些都需要考虑,一般格式的字符串和相应的字符串解析。这样做的努力取决于您需要计数的强健程度 - 例如,如果您需要检测无效格式字符串,则需要付出更多努力。

+2

并不那么简单。您还需要考虑双'*'和标志的情况;例如'%+ *。* f'。你需要实质上实现完整的格式字符串解析器。 – user694733

+0

@ user694733。对于OP给出的例子,我的回答就足够了,但我同意 - 其他例子我不会/我会添加关于限制的评论以及其他需要尽快完成的事情。 – Peter

2

我不知道为什么你需要这个,但是你的问题可能this way(从这个问题接受的答案:Variadic macro trick)来解决。

正如评论中所建议的那样,您可以将printf的调用包装为一个宏,该宏将首先计算所需的参数数量,然后继续执行任何您想要的操作。从博客文章

代码:

#define VA_NUM_ARGS(...) VA_NUM_ARGS_IMPL(__VA_ARGS__, 5,4,3,2,1) 
#define VA_NUM_ARGS_IMPL(_1,_2,_3,_4,_5,N,...) N 

// to verify, run the preprocessor alone (g++ -E): 
VA_NUM_ARGS(x,y,z) 
+0

是的,我真的用这个:http://stackoverflow.com/a/33349105/199554。 – Wim