bool3max
bool3max

Reputation: 2865

Argument to printf to be used as an argument to format specifier

Suppose I have the following function:

void fprint(float f, int ds) {
    printf("%.%df\n", ds, f);
}

I want the caller to specify the float to print, as well as the number of digits after the decimal point. (indicated by the .%d specifier)

However, when compiling this I get 2 warnings:

./sprint.h: In function ‘fprint’:
./sprint.h:19:14: warning: conversion lacks type at end of format [-Wformat=]
     printf("%.%df\n", ds, f);
          ^

and

./sprint.h:19:12: warning: too many arguments for format [-Wformat-extra-args]
     printf("%.%df\n", ds, f);
            ^~~~~~~~~

And when calling it: fprint(3.1422223f, 3);, it produces the output: %df. I also tried swapping the order of the arguments in the function declaration, but it produces the same warnings.

My question is: how can I inject a format specifier (such as %d in this case) into an existing format specifier?

Upvotes: 1

Views: 2765

Answers (2)

Ry-
Ry-

Reputation: 224904

You can use an asterisk with printf to specify that a width or precision is given by an argument – no need to create a dynamic format string.

printf("%.*f", ds, f);

man-pages’s printf(3):

Precision

An optional precision, in the form of a period (.) followed by an optional decimal digit string. Instead of a decimal digit string one may write * or *m$ (for some decimal integer m) to specify that the precision is given in the next argument, or in the m-th argument, respectively, which must be of type int. If the precision is given as just ., the precision is taken to be zero. A negative precision is taken as if the precision were omitted. This gives the minimum number of digits to appear for d, i, o, u, x, and X conversions, the number of digits to appear after the radix character for a, A, e, E, f, and F conversions, the maximum number of significant digits for g and G conversions, or the maximum number of characters to be printed from a string for s and S conversions.

Upvotes: 7

Richard Chambers
Richard Chambers

Reputation: 17573

The printf() format string does not need to be a constant text string. It can also be a character string variable or a character array that contains a format specifier.

char fmt[256];
int  lVal = 5;

strcpy (fmt, "this %d\n");
printf (fmt, lVal);

By using a character string for the format specifier, you can do any modifications you want so long as the argument list supplied to the printf() function agrees with the format string.

You can also do the fly changes by concatenating pieces of a format specifier to build a complete format string or you can build a format specifier string using a function such as sprintf().

Upvotes: 0

Related Questions