syntaxe Scanf -% 6d et% -6D et% 0D
-
24-10-2019 - |
Question
Quelles sont les différences entre l'utilisation scanf
avec les formats de type suivant, lorsque l'entrée est en cours d'analyse par rapport 123456
quand elle est en 123
:
-
%6d
-
%-6d
-
%0d
Quelles sont les différences dans la sortie?
La solution
I ended up just trying it with GCC 4.3.4, and got the following:
%6d
: Works fine; only reads 6 characters (so if you try to read123456789
it will only read123456
)%-6d
: Emits the warning:warning: unknown conversion type character '-' in format
Doesn't read anything, and the int being written to is unmodified
%0d
: Emits the warning:warning: zero width in scanf format
Reads as though there were no width in the format specifier (
%d
)
I haven't checked the spec to see if those results are mandated or just how GCC handles it (EDIT: AndreyT found it)
Autres conseils
The %-6d
is an invalid format specifier. There are no format specifiers with -
in them in scanf
.
In %6d
the 6
part is called maximum field width. It works with all format specifiers (not only with d
) and specifies the maximum number of characters to read before any format-specific conversion is performed. For example, if input sequence is 1234567
, then %3d
will read and convert 123
and %6d
will read and convert 123456
.
The %0d
is an invalid format specifier. Maximum field width in scanf
must be a non-zero integer (see 7.19.6.2/3 in the language specification).
So, that leaves us with %6d
as the only meaningful format specifier among the three you provided. Under these circumstances the question about differences in output (in results?) makes little sense.
EDIT: One can probably argue that in %-6d
the -6
part is the maximum field width, which satisfies the standard requirement of being non-zero decimal integer. However, in C language terminology a decimal integer as a lexical element is a sequence of digits and digits only. It is not allowed to include a sign. I.e. neither -6
nor +6
are decimal integers. Every time you use -6
or +6
as integers in your program it is actually unary -
and +
operator lexeme followed by decimal integer lexeme. So, since the specification of scanf
requires a non-zero decimal integer as maximum field width, it must be a sign-less integer.
Here's what I think will happen: %6d will get you the first 6 digits of the number, %-6d will probably not work as you expect, since - is more of an output alignment specifier. %0d would mean you want only 0 characters, which would probably not work as expected.
Both %-6d
and %0d
are invalid conversion specifications for scanf
, so the behavior for those cases will be undefined. See the language standard, § 7.19.6.2, ¶ 3.
I'll assume, like Arkadiy, that you really meant printf-style formatting, since you refer to "output". I'll also assume that you're using C (as the tag suggests).
If you run:
printf("%6d %-6d %0d", num1, num2);
...you'll end up with compiler errors (or, worse still, runtime bugs), as you haven't supplied enough arguments for three formats.
I've a feeling that that's not what you were asking, though. Let's assume that you actually run:
// (I've added some extra stuff to show how the formatting works.)
printf("'%6d'/'%-6d'/'%0d'", num2, num2, num2);
...you'll get:
' 123'/'123 '/'123'
Normally, if the field width (6 in this case) is wide enough, numbers are right-aligned, space-padded. If you put a '-' before the field width, they will be right-aligned, space-padded.
The subtlety here is in the "%0d" format. You might think you're specifying a zero-width field...and you'd be wrong. The first thing after the '%' is an option flag, and '0' is a valid flag. It means, "If the field width is wider than the content, left-pad with zeroes." In this case, you haven't supplied a field width (the '0' is a flag, remember?), so the '0' flag has no effect: the field will be as wide as the content requires.
There's an even worse subtlety, though. If you specified "%-06d", you'd get right-padding with zeroes, right? Um, no. The '-' flag overrides the '0' flag, whichever order they're supplied. You'd get '123 '.