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

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>

Related

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.

How to control the number of digits to appear after the decimal-point character for a double variable?

I want to print n number of digits after decimal while printing a number of datatype double. However, integer n must be obtained from user using scanf().
double pi = acos(-1);
int n;
printf("\nEnter the number of decimal digits required : ");
scanf("%d",&n);
Now, how to use printf() to print n number of decimal digits of pi?
Quoting C11, chapter §7.21.6.1/p4, for the precision option,
Each conversion specification is introduced by the character %. After the %, the following
appear in sequence:
An optional precision that gives [...] the number of digits to appear after the decimal-point
character for a, A, e, E, f, and F conversions, [...] The precision takes the form of a period (.) followed either by an
asterisk * (described later) or by an optional decimal integer; [...]
and, in paragraph 5,
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. [...]
So, you can use the format
printf("%.*f", precision, variable);
like
printf("%.*f", n, pi);
to use the precision n taken from user.

(GCC) Dollar sign in printf format string

I've seen the following line in a source code written in C:
printf("%2$d %1$d", a, b);
What does it mean?
It's an extension to the language added by POSIX (C11-compliant behaviour should be as described in an answer by #chux). Notation %2$d means the same as %d (output signed integer), except it formats the parameter with given 1-based number (in your case it's a second parameter, b).
So, when you run the following code:
#include <stdio.h>
int main() {
int a = 3, b = 2;
printf("%2$d %1$d", a, b);
return 0;
}
you'll get 2 3 in standard output.
More info can be found on printf man pages.
Per the C spec C11dr 7.21.6.1
As part of a print format, the first % in "%2$d %1$d" introduces a directive. This directive may have various flags, width, precision, length modifier and finally a conversion specifier. In this case 2 is a width. The next character $ is neither a precision, length modifier nor conversion specifier. Thus since the conversion specification is invalid,
... the behavior is undefined. C11dr 7.21.6.1 9
The C spec discusses future library directions. Lower case letters may be added in the future and other characters may be used in extensions. Of course $ is not a lower case letter, so that is good for the future. It certainly fits the "other character" role as $ is not even part of the C character set.
In various *nix implementations, $ is used as describe in Linux Programmer's Manual PRINTF(3). The $, along with the preceding integer defines the argument index of the width.

%.#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.

Formatting floating point numbers in C [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Avoid trailing zeroes in printf()
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
FILE *file;
double n;
file = fopen("fp.source", "r");
while(!feof(file)) {
fscanf(file, "%lf", &n);
printf("Next double:\"%lf\"\n", n);
}
fclose(file);
return 0;
}
Hi I am trying to scan for floating point numbers and I have gotten it to work, but I get trailing zeroes that I don't want. Is there a way to avoid this? For example, the current output I get is:
Next double:"11.540000"
When in reality I would like:
Next double:"11.54"
That's not a problem with scanning. That is a problem with printf formatting.
From the documentation (emphasis mine):
f, F
The double argument shall be converted to decimal notation in the style "[-]ddd.ddd", where the number of digits after the radix character is equal to the precision specification. If the precision is missing, it shall be taken as 6; if the precision is explicitly zero and no '#' flag is present, no radix character shall appear. If a radix character appears, at least one digit appears before it. The low-order digit shall be rounded in an implementation-defined manner.
You probably want %g (again, emphasis mine):
g, G
The double argument shall be converted in the style f or e (or in the style F or E in the case of a G conversion specifier), with the precision specifying the number of significant digits. If an explicit precision is zero, it shall be taken as 1. The style used depends on the value converted; style e (or E ) shall be used only if the exponent resulting from such a conversion is less than -4 or greater than or equal to the precision. Trailing zeros shall be removed from the fractional portion of the result; a radix character shall appear only if it is followed by a digit or a '#' flag is present.
Is there a way to avoid this?
Yes, just format the output correctly:
printf("Next double:\"%.0lf\"\n", n);
The .0 in the printf format string indicates that you don't want to print any digits after the decimal point. You can change the 0 to some other value if you want one, two, three or more digits after the decimal.
Try this.
printf("Next double:\"%l.0f\"\n", n);
Here's a good reference for string format specifiers.
http://www.cplusplus.com/reference/cstdio/printf/

Resources