Set precision dynamically using sprintf - c

Using sprintf and the general syntax "%A.B" I can do this:
double a = 0.0000005l;
char myNumber[50];
sprintf(myNumber,"%.2lf",a);
Can I set A and B dynamically in the format string?

Yes, you can do that. You need to use an asterisk * as the field width and .* as the precision. Then, you need to supply the arguments carrying the values. Something like
sprintf(myNumber,"%*.*lf",A,B,a);
Note: A and B need to be type int. From the C11 standard, chapter §7.21.6.1, fprintf() function
... a field width, or precision, or both, may be indicated by an asterisk. In
this case, an int argument supplies the field width or precision. The arguments specifying field width, or precision, or both, shall appear (in that order) before the argument (if any) to be converted. A negative field width argument is taken as a - flag followed by a positive field width. A negative precision argument is taken as if the precision were omitted.

Yes - You use "*" e.g.
sprintf(mynumber, "%.*lf", 2, a);
See http://linux.die.net/man/3/sprintf

Related

Issue in Format Specifiers of C

How is %+8.9d different from %8.9d in C?
Let's take an example
int a=444;
float b=444;
printf("%8.9d",a);
printf("%8.9f",b);
printf("%+8.9d",a);
printf("%+8.9f",b);
Output:
000000444
444.000000000
+000000444
+444.000000000
Why are 6 zeros present before the number? (that too only in integer numbers)
What is significance of + here?
How is + getting printed in the output?
Why are 6 zeros present before the number?
You requested for a minimum of 9 digits to appear (when printing the int).
Quote https://en.cppreference.com/w/c/io/fprintf,
(optional) . followed by integer number or *, or neither that specifies precision of the conversion. In the case when * is used, the precision is specified by an additional argument of type int, which appears before the argument to be converted, but after the argument supplying minimum field width if one is supplied. If the value of this argument is negative, it is ignored. If neither a number nor * is used, the precision is taken as zero. See the table below for exact effects of precision.
From the referenced table, for d:
Precision specifies the minimum number of digits to appear. The default precision is 1. If both the converted value and the precision are ​0​ the conversion results in no characters.
How is + getting printed in the output?
You requested for a the sign of the number to appear.
Quote https://en.cppreference.com/w/c/io/fprintf,
+: the sign of signed conversions is always prepended to the result of the conversion (by default the result is preceded by minus only when it is negative)

Printf format string maximum width value (padding) %(??)d%n

What is the maximum width value I can put in the %d format specifier? For example:
int c=0;
printf("%1234567899d%n",0,&c);
printf("%d",c);
When I use large values the written value of c is 0. Why is that?
Although it's not stated explicitly, the type of the field width is most likely an int. This is because if the field width is given as * then an int argument is expected.
Section 7.21.6.1p5 of the C standard regarding the fprintf function (any by extension printf) states the following regarding field witdh:
As noted above, a field width, or precision, or both, may be indicated
by an asterisk. In this case, an int argument supplies the
field width or precision. The arguments specifying field
width, or precision, or both, shall appear (in that order)
before the argument (if any) to be converted. A negative
field width argument is taken as a - flag followed by a
positive field width. A neg ative precision argument is
taken as if the precision were omitted.
I tested this on CentOS 7 and Ubuntu 18, and the largest width I could specify was 2147483614 which is 33 less than the max value for a signed 32 bit int. If I use anything larger the first printf prints nothing and c remains 0.
Go generally speaking, the largest value you can expect for c would be INT_MAX, however the exact value will vary based on the implementation.
What is the maximum width value I can put in the %d format specifier?
The limit may be as small as 4095.
Aside from issues with specifying a width outside the positive int range, long output can incur environmental limits.
Environmental limits (fprintf)
The number of characters that can be produced by any single conversion shall be at least 4095. C17dr § 7.21.6.1 15
As I see this, an attempt to "%(some large value)d" print more than 4K (or some greater implementation limit) characters is UB.
Also for output to a text file:
Environmental limits
An implementation shall support text files with lines containing at least 254 characters, including the terminating new-line character. The value of the macro BUFSIZ shall be at least 256. C17dr § 7.21.2 9
Although stdout with printf() is not a file, with re-directed output and freopen(), printf() may be subject to the above constraint.
Then printing an int with many digits can form a line exceeding 254 and some weak file system may not handle long lines.
Such a small 254 limit for a line length I have never seen, so I only include it as a reference, yet do not see it as a modern true limitation.

How can I print "%#s" where # represent the spaces, but this spaces amount have to change depending on the input? [duplicate]

In order to determine the size of the column in C language we use %<number>d.
For instance, I can type %3d and it will give me a column of width=3.
My problem is that my number after the % is a variable that I receive, so I need something like %xd (where x is the integer variable I received sometime before in my program).
But it's not working.
Is there any other way to do this?
You can do this as follows:
printf("%*d", width, value);
From Lee's comment:
You can also use a * for the precision:
printf("%*.*f", width, precision, value);
Note that both width and precision must have type int as expected by printf for the * arguments, type size_t is inappropriate as it may have a different size and representation on the target platform.
Just for completeness, wanted to mention that with POSIX-compliant versions of printf() you can also put the actual field width (or precision) value somewhere else in the parameter list and refer to it using the 1-based parameter number followed by a dollar sign:
A field width or precision, or both, may be indicated by an asterisk ‘∗’ or an asterisk followed by one or more decimal digits and a ‘$’ instead of a digit string. In this case, an int argument supplies the field width or precision. A negative field width is treated as a left adjustment flag followed by a positive field width; a negative precision is treated as though it were missing. If a single format directive mixes positional (nn$) and non-positional arguments, the results are undefined.
E.g., printf ( "%1$*d", width, value );

Large field widths in printf() in C

Do the C standards give any excuse for the program below not to produce gigabytes of spaces on its standard output?
#include <stdio.h>
int main()
{
// 2^64 = 18446744073709551616
printf("x%18446744073709551619dx\n", 42);
return 0;
}
Tested on Mac OS X 10.8 and on Linux, I get x 42x.
The C11 standard says (7.21.6.1:4): “An optional minimum field width. If the converted value has fewer characters than the field width, it is padded with spaces (by default) on the left (or right, if the left adjustment flag, described later, has been given) to the field width. The field width takes the form of an asterisk * (described later) or a nonnegative decimal integer.”
The wording in C99 is the same.
When the field width is given as *, then the corresponding argument is obtained as an int (7.12.6.1:5). But it does not seem to be said that the hardcoded field width should fit in an int.
Although it doesn't address the specific question of the field width encoding limit, note that §7.21.6.1/15 states "The number of characters that can be produced by any single conversion shall be at least 4095." So even if an implementation does parse 2^64 + 3 correctly, it's conforming to output 4094 spaces instead of "gigabytes".
Although the C standard does not define a maximum value I guess that every compiler has a maximum value for it.
Here is a similar question:
size limit of printf conversion specification

Set variable text column width in printf

In order to determine the size of the column in C language we use %<number>d.
For instance, I can type %3d and it will give me a column of width=3.
My problem is that my number after the % is a variable that I receive, so I need something like %xd (where x is the integer variable I received sometime before in my program).
But it's not working.
Is there any other way to do this?
You can do this as follows:
printf("%*d", width, value);
From Lee's comment:
You can also use a * for the precision:
printf("%*.*f", width, precision, value);
Note that both width and precision must have type int as expected by printf for the * arguments, type size_t is inappropriate as it may have a different size and representation on the target platform.
Just for completeness, wanted to mention that with POSIX-compliant versions of printf() you can also put the actual field width (or precision) value somewhere else in the parameter list and refer to it using the 1-based parameter number followed by a dollar sign:
A field width or precision, or both, may be indicated by an asterisk ‘∗’ or an asterisk followed by one or more decimal digits and a ‘$’ instead of a digit string. In this case, an int argument supplies the field width or precision. A negative field width is treated as a left adjustment flag followed by a positive field width; a negative precision is treated as though it were missing. If a single format directive mixes positional (nn$) and non-positional arguments, the results are undefined.
E.g., printf ( "%1$*d", width, value );

Resources