Leading zeros default behaviour with ISO C99 printf ("%Nd")? - c

I've just spotted the following in the C99 ISO standard, 7.19.6.1 The fprintf function, subsection 6, detailing the conversion flags, specifically the 0 flag:
0: d, i, o, u, x, X, a, A, e, E, f, F, g, and G conversions, leading zeros (following any indication of sign or base) are used to pad to the field width rather than performing space padding, except when converting an infinity or NaN.
So far so good, I know that the following lines will produce the shown output:
printf ("%5d\n", 7); // produces " 7"
printf ("%05d\n",7); // produces "00007"
However, in subsection 8 detailing the conversion modifiers, I see:
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.
That's plainly not the case since the default behaviour is to pad with spaces, not zeroes. Or am I misreading something here?

You're confusing precision and field width:
printf("%.5i", 1); // prints "00001", precision = 5
printf("%5i", 1); // prints " 1", field width = 5
printf("%5.3i", 1); // prints " 001", field width = 5, precision = 3

Related

How to use printf so that zeros are printed with decimals

I'm running a simple calculation in C, for which, sometimes, the result is exactly 0. I then print these results using something like printf("%0.4g", result). If the result is not 0, it does what I want it do, e.g., the output may be 1.796e+04. However, if the result is exactly 0, which it often is, the output will be 0.
My question is, what can I do to print 0.0000, with 4 decimals, even though the number there might be exactly 0?
To have 4 decimals, you have to specify .5. To have 0 print as 0.0, you have to add #.
printf("%#.5g", 0.0);
Note that this will print 4 decimal places, unlike %0.4g, that will print 3 decimal places.
The 0 before the dot . is unneeded. It is used to specify, that the field should be prefixed with zeros not with spaces when matching a field length. But you don't specify the field length, so no prefixing takes place, so the 0 can be left out.
Using the %g format with the # modifier probably does what you want.
The POSIX specification for printf() (which is generally a superset of C11 §7.21.6.1 The printf() function, but here POSIX says the same as C11) requires:
g, G — The double argument representing a floating-point number shall be converted in the style f or e (or in the style F or E in the case of a G conversion specifier), depending on the value converted and the precision. Let P equal the precision if non-zero, 6 if the precision is omitted, or 1 if the precision is zero. Then, if a conversion with style E would have an exponent of X:
If P > X >= -4, the conversion shall be with style f (or F) and precision P-(X+1).
Otherwise, the conversion shall be with style e (or E) and precision P -1.
Finally, unless the '#' flag is used, any trailing zeros shall be removed from the fractional portion of the result and the decimal-point character shall be removed if there is no fractional portion remaining.
A double argument representing an infinity or NaN shall be converted in the style of an f or F conversion specifier.
So, the trailing zeroes you want are retained by specifying # in the conversion specification — "%#0.4g".
If you want 4 digits after the decimal point though, you need to use "%#0.5g".
Sample code:
#include <stdio.h>
int main(void)
{
double data[] = { 0.0, -0.0000001, +1.234E-6, 1.796e+04, 3.14159265, 6.022140857E+23, 6.62607004E-34 };
enum { NUM_DATA = sizeof(data) / sizeof(data[0]) };
for (int i = 0; i < NUM_DATA; i++)
printf("%20.10g = %#0.4g\n", data[i], data[i]);
return 0;
}
Output (Mac running macOS 10.14.4 Mojave — home-built GCC 9.1.0 compiler):
0 = 0.000
-1e-07 = -1.000e-07
1.234e-06 = 1.234e-06
17960 = 1.796e+04
3.14159265 = 3.142
6.022140857e+23 = 6.022e+23
6.62607004e-34 = 6.626e-34
You do recognize approximations to Planck's Constant and Avogadro's Number, don't you?
the statement
printf("%0.4e\n", res);
might solve your problem!
You can use
printf("%0.4f",YourVeriable);

Why this formatted output is getting printed while using float?

In this underlying code:
float j=9.01;
printf("%2.3f \n",j);
the output is 9.010, shouldn't it be like 2 character wide reserved for the entire j which includes 3 for the decimal - so it makes the no. before decimal i.e. 9 disappear and only 01 to be printed?
Where am I going wrong in this?
Let's quote the man page:
Field Width
In no case does a nonexistent or small field width cause truncation of a field; if the result of a conversion is wider than the field width, the field is expanded to contain the conversion result.
and
The precision
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 field width is too small, but fields are never truncated so that doesn't matter.
The part after the period is clearly the precision, and you ask for three digits.

C printf difference between 0 flag & width attribute and precision flag

I'm currently learning the printf function of libc and I don't understand, what is the difference between:
printf("Test : %010d", 10);
using the 0 flag and 10 as width specifier
and
printf("Test : %.10d", 10);
using 10 as precision specifier
That produce the same output: Test : 0000000010
We'll start with the docs for printf() and I'll highlight their relevant bits.
First 0 padding.
`0' (zero)
Zero padding. For all conversions except n, the converted value is padded on the left with zeros rather than blanks. If a precision is given with a numeric conversion (d, i, o, u, i, x, and X), the 0 flag is ignored.
And then precision.
An optional precision, in the form of a period . followed by an optional digit string. If the digit string is omitted, the precision is taken as zero. 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 decimal-point 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 conversions.
%010d says to zero-pad to a minimum width of 10 digits. No problem there.
%.10d", because you're using %d, says the minimum number of digits to appear is 10. So the same thing as zero padding. %.10f would behave more like you expected.
I would recommend you use %010d to zero pad. The %.10d form is a surprising feature that might confuse readers. I didn't know about it and I'm surprised it isn't simply ignored.
Both formats produce the same output for positive numbers, but the output differs for negative numbers greater than -1000000000:
printf("Test : %010d", -10); produces -000000010
whereas
printf("Test : %.10d", -10); produces -0000000010
Format %010d pads the output with leading zeroes upto a width of 10 characters.
Format %.10d pads the converted number with leading zeroes upto 10 digits.
The second form is useful if you want to produce no output for value 0 but otherwise produce the normal conversion like %d:
printf("%.0d", 0); // no output
printf("%.0d", 10); // outputs 10
Also note that the initial 0 in the first form is a flag: it can be combined with other flags in any order as in %0+10d which produces +000000010 and it can be used with an indirect width as in printf("%0*d", 10, 10); which produces 0000000010.
There's no difference besides maybe a purely conceptual one.
In the first case you are just filling the blank area with completely independent padding 0 characters. In the second case these zeros are leading zeros created when converting your argument value. (This is admittedly very contrived.)
In any case these zeros look, smell and quack the same.
However, in general case there's one obscure specific situation when precision behaves differently from padded field-width: when you are asking for zero field width and print zero value. When zero precision is used, zero values are simply not printed at all. When zero field-width is used, zero values will appear as usual
printf("%00d\n", 0); // prints '0'
printf("%.0d\n", 0); // prints nothing
Obviously this is also a very contrived situation, since no padding occurs in this case.
In your second case you probably expected 10.0000000000 - but %d is only for integers. The specification says:
For integer specifiers (d, i, o, u, x, X): precision specifies the minimum number of digits to be written.
(Precision is the part started with . , so in your case 10 .)
So, with %.10d you specified at least 10 digits to express the two-digit number, so it is completed with the 8 leading zeroes.
It means that both %010d and %.10d will produce the same result.

How can variable field width be implemented with printf()?

The question is :
How can variable field width be implemented using printf()? That is, instead of %8d, the width should be specified at run time.
I came across some C code on the Internet based on the question above but as I am new to C programming I haven't been able to make heads or tails of the code.
I am posting the code below:
#include <stdio.h>
int main()
{
const char text[] = "Hello world";
int i;
for ( i = 1; i < 12; ++i )
{
printf("\"%.*s\"\n", i, text);
}
return 0;
}
First of all, let me tell you, the code you have shown is about controlling the precision, not the field width. For a shortened form**
%A.B<format specifier>
A denotes the field width and B makes the precision.
Now, quoting the C11 standard, chapter §7.21.6.1, fprintf() (emphasis mine)
Each conversion specification is introduced by the character %. 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 number of digits to appear after the decimal-point
character for a, A, e, E, f, and F conversions, the maximum number of significant
digits for the g and G conversions, or the maximum number of bytes to be written for s 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. If a precision appears with any other
conversion specifier, the behavior is undefined.
and
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. [...]
So, in your case,
printf("\"%.*s\"\n", i, text);
the precision will be supplied by i which can hold different values at run-time.
The complete format (broken down in separate lines for ease of readability)
%
<Zero or more flags>
<optional minimum field width>
<optional precision>
<optional length modifier>
<A conversion specifier character>

%.#s format specifier in printf statement in c

Please explain the output. What does %.#s in printf() mean?
#include<stdio.h>
#include <stdlib.h>
int main(int argc,char*argv[]){
char *A="HELLO";
printf("%.#s %.2s\n",A,A);
return 0;
}
OUTPUT:
#s HE
It's undefined behavior. # in printf format specifier means alternative form, but according to the standard, # is only used together with o, a, A, x, X, e, E, f, F, g, G, not including s.
C11 §7.21.6.1 The fprintf function Section 6
# The result is converted to an ‘‘alternative form’’. For o conversion, it increases
the precision, if and only if necessary, to force the first digit of the result to be a
zero (if the value and precision are both 0, a single 0 is printed). For x (or X)
conversion, a nonzero result has 0x (or 0X) prefixed to it. For a, A, e, E, f, F, g, and G conversions, the result of converting a floating-point number always
contains a decimal-point character, even if no digits follow it. (Normally, a decimal-point character appears in the result of these conversions only if a digit follows it.) For g and G conversions, trailing zeros are not removed from the result. For other conversions, the behavior is undefined.
For example, on my machine, output is different: %.0#s HE
%.1s is used to print the first character of the string
%.2s is used to print the first two characters of the string
%.3s is used to print the first three characters of the string and so on
where # : alternative form of the conversion is performed is a flag which have an optional usage with the format parameter in printf() and fprintf() functions etc.
But as #Yu Hao said # is only used together with o, a, A, x, X, e, E, f, F, g, G, not including s.
in your case %.#s usage is Wrong.
Example usage from reference given by #WhozCraig :
printf("Hexadecimal:\t%x %x %X %#x\n", 5, 10, 10, 6);
printf("Octal:\t%o %#o %#o\n", 10, 10, 4);
I agree with Yu Hao's answer that it is undefined behavior, but I think the reason is different. Yes, the # character works as a flag to convert the result to an alternative format. Yes, the # flag is undefined for strings. But in this case, the # is not a flag, it's a precision. It's still undefined, but the reason is different
The C11 standard at §6.21.6.1 says that the % sign is followed in sequence by:
Zero or more flags (including #)
An optional minimum field width
An optional precision
An optional length modifier
A conversion specifier character
Except for the conversion specifier, these are all optional. But the order in which they appear is always as above. So flag, if present, has to be first, immediately after the % character. Here what follows the % is not something indicating a flag, it is a period: %., indicating precision.
When you have %.# in your format string for printf(), the period indicates that the following character is the precision for the conversion specification that follows. I.e., the # in your code specifies the precision for the string s, not a flag. To be a flag, it would have to directly follow the % character, without the intervening period.
With regard to precision, the C standard §7.21.6.1 says this:
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. If a precision appears with any other conversion
specifier, the behavior is undefined.
Since in your format string you have %.#s, and # is neither an asterisk * nor a decimal integer, the result is undefined.
So to be extremely exact about why your code is undefined, I think it's because the # character appears in place of a legal precision, not because it is an illegal flag for the %s conversion. It would be illegal as a flag, of course, but that's not what is precisely (har har) happening here.

Resources