About printf format string in C - c

Let's take the following program:
#include <stdio.h>
int main()
{
long t =57 ;
printf("[%+03ld]", t);
}
and it's output:
[+57]
I am somehow confused: I told him to pad the output to width 3 (03ld), with zeroes, however it seems that if I force the output to put a plus sign before the number (+) it will not add the required zeroes if the length of the number is already 2 digits (as in 57). For numbers <10 it pads with 1 zero.
From http://www.cplusplus.com/reference/cstdio/printf/
(0) -> Left-pads the number with zeroes (0) instead of spaces when padding is specified (see width sub-specifier).
(+) -> Forces to preceed the result with a plus or minus sign (+ or -) even for positive numbers. By default, only negative numbers are preceded with a - sign.
(width) -> Minimum number of characters to be printed. If the value to be printed is shorter than this number, the result is padded with blank spaces. The value is not truncated even if the result is larger.
So I just need a clarification ... The (width) specifier from the quote above refers to the full length of the output string (ie: the characters that will be printed) controlled by this format specifier ("%+03ld") or the full length of the characters of the number that is going to be printed?

Yes, the width specifier refers to the width of the entire formatted result, +57 in your case. This makes it useful for printing columnar text for easy reading on screen (important if you're using C to write an old-school text utility!).

C standard is rather precise that converted value is taken a whole. From C11 §7.21.6/2 (emphasis mine):
The fprintf function writes output to the stream pointed to by stream,
under control of the string pointed to by format that specifies how
subsequent arguments are converted for output.
along with §7.21.6/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.

As you quoted "Minimum number of characters to be printed.", so "+" is just another character for printf. Btw the zeros "0" are just characters aswell and have nothing to do with numbers. It could be any character.

Yes, the field width refers to the complete, converted value including decimal dots, signs etc.

You asked for a 3 characters length format and get 3 characters +57. If you want the 0 to be present, just use printf("[%+04ld]", t); and you'll get +057.

Related

What is the meaning of this format `%02hhx`?

I saw in some functions that in order to convert number to hexadecimal format, using this format: printf("%02hhx", some_char); , but I don't understand why, and what is the meaning of this format ?
Format string "%02hhx" means:
0: Results that would require less than specified field width shall be printed with leading 0s.
2: use at least 2 characters to format the value
x Print in hexadecimal format.
hh The provided parameter for x is only a char, not an int For values 0..127 it doesn't matter if you add the hh but values above could get sign extended and would be printed with lots of leading F.
The result will just be a hexadecimal value with 2 digits.

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

Meaning of "." in printf

I was just reading the classic K&R and encountered the following syntax:
printf("%.*s",max,s);
What is the meaning of "." here?When I don't apply a "." here,then whole string is printed,but when we don't apply a "." ,atmost max characters are printed.I will be really thankful if anyone could explain this.
In %.*s, the .* limits the number of bytes that will be written. If this were written with a numeral included, such as %.34s, then the numeral would be the limit. When an asterisk is used, the limit is taken from the corresponding argument to printf.
From C 2011 (N1570) 7.21.6.1 4, describing conversion specifications for fprintf et al:
An optional precision that gives … 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.
It specifies the "Character String Maximum field width"
The precision within a string format specifies the maximum field width:
%2.6s
specifies a minimum width of 2 and a maximum width of 6 characters. If the string is greater than 6 characters, it will be truncated.
A printf format string allows specifying width and precision.
Width, such as %25s, tells printf to pad the string to the width of 25 characters, inserting spaces before the string. (If the string is wider than 25 characters, it is still printed in its entirety.)
A "precision" applied to a string format, such as %.25s, limits the length of the printed string to 25 characters. A string of 3 characters will be printed fully (with no padding), and a string of 30 characters will be missing its last five characters.
%.*s avoids hardcoding the precision in the format, specifying it instead as an integer argument to printf, in your case max.
First of all, K&R is the original implementation of C, which is different from the current specification. If you want specific information about K&R C, then consult specific documentation.
From the current C standard:
An optional precision that gives (...) 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.
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf
Similar documentation is available everywhere online for multiple standards or implementations:
glibc
http://www.gnu.org/software/libc/manual/html_node/Output-Conversion-Syntax.html#Output-Conversion-Syntax
POSIX
http://pubs.opengroup.org/onlinepubs/9699919799/functions/fprintf.html
Microsoft C runtime
http://msdn.microsoft.com/en-us/library/56e442dc.aspx
Dot has different meaning with different format strings . If you use a.b with %f , then b gives length . a gives number of decimal points . if you use a.b with %s , a will give minimum length of the string . whereas b gives maximum length of the string that will be printed .
It actually print the character in limited number and commanded format based on the function passed to printf,in this case it should print the specific of "max"

Should printf("% .0d",0) print a space? printf("%+.0d",0) print a plus?

glibc's printf("% .0d",0) prints a space, and printf("%+.0d",0) prints a plus sign, and the glib printf test checks for this behavior. But is it correct? From the standard (7.19.6.1):
+ The result of a signed conversion always begins with a plus or minus sign. (It begins with a sign only when a negative value is converted if this flag is not specified.)
space If the first character of a signed conversion is not a sign, or if a signed conversion results in no characters, a space is prefixed to the result. If the space and + flags both appear, the space flag is ignored.
However, regarding precision for the d specifier:
The result of converting a zero value with a precision of zero is no characters.
Naturally this "no characters" rule does not preclude padding the field to the requested width, but as far as I can tell, the prefixed space or + is part of the conversion, and thus subject to the "no characters" rule.
Has this matter ever been clarified?
No, it's talking about the basic conversion without modifiers; that's why the modifiers specifically say what they do when the basic conversion produces no characters.

Resources