What's the difference between printf("%.d", 0) and printf("%.1d", 0)? - c

I'm working on recoding printf and I'm blocked for a moment now with the precision flag. So I read that the default precision when type conversion specifier is d is 1:
So I supposed that there is no difference between %.d and %.1d, but when I test:
printf(".d =%.d, .1d= %.1d", 0, 0);
I do find one:
.d =, .1d= 0

If you use . after % without specifying the precision, it is set to zero.
From the printf page on cppreference.com:
. 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. If the value of
this argument is negative, it is ignored. If neither a number nor *
is used, the precision is taken as zero.
It defaults to 1 if you use %d (without .):
printf("d = %d, 1d= %1d", 0, 0);
# Output: d = 0, 1d= 0

The C18 standard - ISO/IEC 9899:2018 - (emphasize mine) states:
"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 non negative 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."
Source: C18, §7.21.6.1/4
Means %.d is equal to %.0d and with that different to %.1d.
Furthermore:
"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. The default precision is 1. The result of converting a zero value with a precision of zero is no characters."
Source: C18, §7.21.6.1/8
That means if you convert a 0 value by using %.d in a printf() call, the result is guaranteed to be no characters printed (which matches to your test experience).

When the precision is set to zero or its value is omitted like
printf( "%.d", x )'
when according to the description of the conversion specifiers d and i (7.21.6.1 The fprintf function)
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. The default precision is 1. The result
of converting a zero value with a precision of zero is no
characters.
Here is a demonstrative program
#include <stdio.h>
int main(void)
{
printf( "%.d\n", 0 );
printf( "%.0d\n", 0 );
printf( "%.1d\n", 0 );
return 0;
}
Its output is
0
That is when the precision is equal to 0 or its value is absent then if 0 is specified as an argument when nothing will be outputted.

Related

How to check against negative numbers (by user input) that are itself unsigned variables?

I'm trying to test against negative numbered variables that are unsigned int. Is that not possible?
It skips the do while loop and outputs a garbage number.
#include<stdio.h>
unsigned int getPositiveInteger(void);
int main(void){
unsigned int i=getPositiveInteger();
printf("The number is %u.\n", i);
return 0;
}
unsigned int getPositiveInteger(void){
int error=0;
unsigned int n=0;
do{
if(error){
printf("The number must be positive!\n");
}
error=0;
printf("What's the number?\n");
scanf("%u", &n);
if(n<1){
error=1;
}
}
while(n<1);
return n;
}
When ran:
What's the number?
-1
The number is 4294967295.
When the input number is signed, scanf with %u produces the value that results from negating the number in the unsigned type, so it always produces a non-negative result.
The specification of the %u conversion for scanf is in C 2018 7.21.6.2 12:
… u Matches an optionally signed decimal integer, whose format is the same as expected for the subject sequence of the strtoul function with the value 10 for the base argument. The corresponding argument shall be a pointer to unsigned integer.
For strtoul, 7.22.1.4 3 says:
… [For base value 10] the expected form of the subject sequence is a sequence of letters and digits representing an integer with the radix specified by base, optionally preceded by a plus or minus sign,…
and 7.22.1.4 5 says:
… If the subject sequence begins with a minus sign, the value resulting from the conversion is negated (in the return type).
Thus, for input characters “-1”, scanf converts “1” to an unsigned value of 1 and then applies the - operator. Arithmetic in unsigned wraps modulo UINT_MAX+1, so the mathematical negation, −1, wraps to −1+UINT_MAX+1, which is UINT_MAX.
To test whether an input is negative, you can read the individual characters and check for a “-” character. To do this, you can either accumulate characters in a temporary buffer and then use sscanf to process them, or you can skip white space characters until you see either a digit or a “-” (or some other character, which you would treat as an error). If it is a “-”, then report an error. If it is a digit, use ungetc to put it back into the input stream, then use scanf.
To store signed numbers you should use signed data types for variable. That's the point of signed data types.

C programming - unsigned int overflow problem

I want to print out an integer type variable which value is 3000000000;
So I wrote the below code then ran it, but the printed value was incorrect. I think the variable is overflowed. But I don't know why.
#include<stdio.h>
int main(void) {
unsigned int num1 = 3000000000;
printf("%d", num1);
}
As far as I know, the maximum value of unsigned integer type variable is (2^32-1 = 4,294,967,296 - 1) when the code complies on Win32 API.
But the printed value is -1294967296.
I have no idea why overflow occurs in my code.
If anyone knows the reason, please let me know :)
Best regards,
I use Microsoft Visual Studio 2015 Professional.
use %u not %d
For printf:
%d is used by:
d, i The int argument is converted to signed decimal notation.The
precision, if any, gives the minimum number of digits that
must appear; if the converted value requires fewer digits, it
is padded on the left with zeros. The default precision is 1.
When 0 is printed with an explicit precision 0, the output is
empty.
%u is used by:
o, u, x, X
The unsigned int argument is converted to unsigned octal (o),
unsigned decimal (u), or unsigned hexadecimal (x and X) nota‐
tion. The letters abcdef are used for x conversions; the let‐
ters ABCDEF are used for X conversions. The precision, if
any, gives the minimum number of digits that must appear; if
the converted value requires fewer digits, it is padded on the
left with zeros. The default precision is 1. When 0 is
printed with an explicit precision 0, the output is empty.
see http://man7.org/linux/man-pages/man3/printf.3.html

Precision field in printf when formatting integer

When I execute these two lines:
printf("%.5d\n", 3); // use of precision filed
printf("%05d\n", 3); // use of 0 flag to prepend with 0
I get the following output:
00003
00003
The same result
So I wonder what is the meaning of the precision field for integer types
For %d, the precision is the minimum number of digits to print.
From the man page:
The precision
An optional precision, in the form of a period ('.') followed by
an optional decimal digit string. Instead of a decimal digit
string one may write "*" or "*m$" (for some decimal integer m) to
specify that the precision is given in the next argument, or in the
m-th argument, respectively, which must be of type int. If the
precision is given as just '.', or the precision is negative, the
precision is taken to be 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 radix character 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 and S conversions.
For positive values, this works out to be the same as giving the same value for the field width and a 0 flag. If the value is negative, the negative sign will take up one character in the width of %05d.
printf("%.5d\n", -3); // use of precision filed
printf("%05d\n", -3); // use of 0 flag to prepend with 0
Output:
-00003
-0003

sscanf %u not intepreting hexadecimal

I'm trying to convert from hexadecimal or decimal text to an unsigned int using the "%u" format specifier of sscanf. The result is not correct, for the value 0x01, sscanf is returning a 0 (0).
According to C++ Reference, the definition of "%u" specifier (highlighting is mine):
i, u Integer Any number of digits, optionally preceded by a sign (+ or -).
Decimal digits assumed by default (0-9), but a 0 prefix introduces octal digits (0-7), and 0x hexadecimal digits (0-f).
According to Harbison & Steele, 3rd Edition:
The u conversion Unsigned decimal conversion is performed.
...
The format of the number read is the same as expected for the input to the strtol function with the value 10 for the base argument; that is a sequence of decimal digits optionally preceded by - or +.
Note that one of the definitions allows "0x" to be specified in the string.
I am using IAR EW compiler with the compilation set to C99 dialect.
Which definition is correct for C99?
I am receiving two different results in the following program.
Here is a test program:
#include <stdio.h>
int main(void)
{
const char text[] = "0x01 1";
unsigned int first_value = 0U;
unsigned int second_value = 0U;
signed int arguments_satisfied = 0;
arguments_satisfied = sscanf(text, "%u %u", &first_value, &second_value);
printf("Arguments scanned: %d, first: %d, second: %d\n",
arguments_satisfied, first_value, second_value);
return EXIT_SUCCESS;
}
According to the current C standard, C11, 7.21.6.2/12, only %i deduces the base from the context, all other specifiers fix the base:
i Matches an optionally signed integer, whose format is the same as expected
for the subject sequence of the strtol function with the value 0 for the
base argument. The corresponding argument shall be a pointer to signed
integer.
o Matches an optionally signed octal integer, whose format is the same as
expected for the subject sequence of the strtoul function with the value 8
for the base argument. The corresponding argument shall be a pointer to
unsigned integer.
u Matches an optionally signed decimal integer, whose format is the same as
expected for the subject sequence of the strtoul function with the value 10
for the base argument. The corresponding argument shall be a pointer to
unsigned integer.
x Matches an optionally signed hexadecimal integer, whose format is the same
as expected for the subject sequence of the strtoul function with the value
16 for the base argument. The corresponding argument shall be a pointer to
unsigned integer.

Integer to floating conversion in C

float f1 = 123.125;
int i1 = -150;
f1 = i1; // integer to floating conversion
printf("%i assigned to an float produces %f\n", i1, f1);
Output:
-150 assigned to an float produces -150.000000
My question is why the result has 6 zeros (000000) after the . and not 7 or 8 or some number?
That's just what printf does. See the man page where it says
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.
(emphasis mine)
It has nothing to do with how 150 is represented as a floating point number in memory (and in fact, it's promoted to a double because printf is varargs).
The number of zeros you see is a result of the default precision used by the %f printf conversion. It's basically unrelated to the integer to floating point conversion.
Because the C standard (§7.19.6.1) says that in the absence of information to the contrary, %f will print 6 decimal places.
f,F A double argument representing a floating-point number is converted to
decimal notation in the style [−]ddd.ddd, where the number of digits after
the decimal-point character is equal to the precision specification. If the
precision is missing, it is taken as 6; if the precision is zero and the # flag is
not specified, no decimal-point character appears.
Floating point arithmetic is not exact. printf is just showing that number of zeroes.
From the documentation:
The default number of digits after the
decimal point is six, but this can be
changed with a precision field. If a
decimal point appears, at least one
digit appears before it. The "double"
value is rounded to the correct number
of decimal places.

Resources