Wim
Wim

Reputation: 11252

Determine number of printf arguments

Is there a standard C/C++ function that, given a printf format string, returns the number of arguments it expects? E.g.:

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

Just counting the number of % in the format string would be a first approximation, which works in the first example, but obviously not in the second and third ones.

I know gcc can do this, since at compile time it complains when the number of arguments (and also their type) actually passed to printf does not match the format string.

Upvotes: 4

Views: 1812

Answers (2)

Peter
Peter

Reputation: 36607

No standard function to do this.

However, it would be easy to implement.

Count the number of % that are not followed by another %. The add 1 for every one of those counted % immediately followed by a *.

When counting runs of % characters, don't allow overlaps. So "%%%d" should result in a value of 1 (not 0, and certainly not 2 or 3).

EDIT - text below added following comment from user694733

This will suffice for format strings along the lines of the three examples you gave. However, as noted by user694733 in comments, this is not the whole story.

In general terms, a format specifier follows the prototype %[flags][width][.precision][length]specifier. The approach above is a starting point, and will work for format strings have have no flags, a possible * in width specifier, no * in the precision specifier, and overlooks length and specifier fields. All of those need to be considered, for a general format string, and the string parsed accordingly. The effort to do that depends on how robust you need your count to be - for example, more effort if you need to detect an invalid format string.

Upvotes: 6

n0p
n0p

Reputation: 3496

I'm not sure why you need this, however your problem might be solved in this way (accepted answer from this question: Variadic macro trick).

As suggested in comments, you can wrap the call of printf into a macro that will first count the number of arguments required and then proceed to whatever you want to do.

Code from blog post:

#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)

Upvotes: 3

Related Questions