How to print a positive number as a negative number via printf - c

While reading about printf(),I found that it can print numbers as positive or negative as desired by the user by following code(for -).But the code doesnt work and the output is a positive value.Please mention where the error is.Thanks
#include<stdio.h>
int main()
{
printf (" %-d\n", 1977);
return 0;
}

From your comments it looks like you misread this page. The - and + specifiers do two completely different things, and neither does what you think '-' should do.
As others have noted, - does left justification. The + specifier prints positive numbers with a leading plus sign (and negative numbers still get a leading minus sign):
printf("%d %d %+d %+d\n", -10, 10, -10, 10);
outputs:
-10 10 -10 +10

printf (" -%d\n", 1977); will output -1997 (bad way to do it), if you would like negative numbers to become positive, do printf (" %d\n", -1 * 1977); (good way to do it)
read the reference for an idea of how format specifiers work

%-d Will left adjust the integer field, it won't flip the sign. Do this instead:
printf (" %d\n", -1977);
Here's the full extract from print(3) under The flag characters:
- The converted value is to be left adjusted on the field bound‐
ary. (The default is right justification.) Except for n con‐
versions, the converted value is padded on the right with
blanks, rather than on the left with blanks or zeros. A - over‐
rides a 0 if both are given.
Update0
I see your true question now: To prepend output with the appropriate sign, use the + flag character to explictly show the sign. Again here is the extract:
+ A sign (+ or -) should always be placed before a number produced
by a signed conversion. By default a sign is used only for neg‐
ative numbers. A + overrides a space if both are used.
And use it like this (The command line printf is mostly identical):
matt#stanley:~/cpfs$ printf "%+d\n" 3
+3
matt#stanley:~/cpfs$ printf "%+d\n" -3
-3
matt#stanley:~/cpfs$ printf "%+u\n" -3
18446744073709551613
Be aware that explicitly requesting the sign won't imply treatment of the corresponding integer as signed as in the %u example above.

Related

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.

C - The %x format specifier

I have a small question. I know that the %x format specifier can be used to read values from the stack in a format string attack.
I found the following code:
%08x%08x%08x%08x
What does the 08 mean? What is it doing exactly? Thanks :)
Break-down:
8 says that you want to show 8 digits
0 that you want to prefix with 0's instead of just blank spaces
x that you want to print in lower-case hexadecimal.
Quick example (thanks to Grijesh Chauhan):
#include <stdio.h>
int main() {
int data = 29;
printf("%x\n", data); // just print data
printf("%0x\n", data); // just print data ('0' on its own has no effect)
printf("%8x\n", data); // print in 8 width and pad with blank spaces
printf("%08x\n", data); // print in 8 width and pad with 0's
return 0;
}
Output:
1d
1d
1d
0000001d
Also see http://www.cplusplus.com/reference/cstdio/printf/ for reference.
%08x means that every number should be printed at least 8 characters wide with filling all missing digits with zeros, e.g. for '1' output will be 00000001
The format string attack on printf you mentioned isn't specific to the "%x" formatting - in any case where printf has more formatting parameters than passed variables, it will read values from the stack that do not belong to it. You will get the same issue with %d for example.
%x is useful when you want to see those values as hex.
As explained in previous answers, %08x will produce a 8 digits hex number, padded by preceding zeros.
Using the formatting in your code example in printf, with no additional parameters:
printf ("%08x %08x %08x %08x");
Will fetch 4 parameters from the stack and display them as 8-digits padded hex numbers.
That specifies the how many digits you want it to show.
integer value or * that specifies minimum field width. The result is padded with space characters (by default), if required, on the left when right-justified, or on the right if left-justified. In the case when * is used, the width is specified by an additional argument of type int. If the value of the argument is negative, it results with the - flag specified and positive field width.
From http://en.wikipedia.org/wiki/Printf_format_string
use 0 instead of spaces to pad a field when the width option is specified. For example, printf("%2d", 3) results in " 3", while printf("%02d", 3) results in "03".

Wrong output from printf of a number

int main()
{
double i=4;
printf("%d",i);
return 0;
}
Can anybody tell me why this program gives output of 0?
When you create a double initialised with the value 4, its 64 bits are filled according to the IEEE-754 standard for double-precision floating-point numbers. A float is divided into three parts: a sign, an exponent, and a fraction (also known as a significand, coefficient, or mantissa). The sign is one bit and denotes whether the number is positive or negative. The sizes of the other fields depend on the size of the number. To decode the number, the following formula is used:
1.Fraction × 2Exponent - 1023
In your example, the sign bit is 0 because the number is positive, the fractional part is 0 because the number is initialised as an integer, and the exponent part contains the value 1025 (2 with an offset of 1023). The result is:
1.0 × 22
Or, as you would expect, 4. The binary representation of the number (divided into sections) looks like this:
0 10000000001 0000000000000000000000000000000000000000000000000000
Or, in hexadecimal, 0x4010000000000000. When passing a value to printf using the %d specifier, it attempts to read sizeof(int) bytes from the parameters you passed to it. In your case, sizeof(int) is 4, or 32 bits. Since the first (rightmost) 32 bits of the 64-bit floating-point number you supply are all 0, it stands to reason that printf produces 0 as its integer output. If you were to write:
printf("%d %d", i);
Then you might get 0 1074790400, where the second number is equivalent to 0x40100000. I hope you see why this happens. Other answers have already given the fix for this: use the %f format specifier and printf will correctly accept your double.
Jon Purdy gave you a wonderful explanation of why you were seeing this particular result. However, bear in mind that the behavior is explicitly undefined by the language standard:
7.19.6.1.9: If a conversion specification is invalid, the behavior is undefined.248) If any argument is not the correct type for the corresponding conversion specification, the behavior is undefined.
(emphasis mine) where "undefined behavior" means
3.4.3.1: behavior, upon use of a nonportable or erroneous program construct or of erroneous data, for which this International Standard imposes no requirements
IOW, the compiler is under no obligation to produce a meaningful or correct result. Most importantly, you cannot rely on the result being repeatable. There's no guarantee that this program would output 0 on other platforms, or even on the same platform with different compiler settings (it probably will, but you don't want to rely on it).
%d is for integers:
int main()
{
int i=4;
double f = 4;
printf("%d",i); // prints 4
printf("%0.f",f); // prints 4
return 0;
}
Because the language allows you to screw up and you happily do it.
More specifically, '%d' is the formatting for an int and therefore printf("%d") consumes as many bytes from the arguments as an int takes. But a double is much larger, so printf only gets a bunch of zeros. Use '%lf'.
Because "%d" specifies that you want to print an int, but i is a double. Try printf("%f\n"); instead (the \n specifies a new-line character).
The simple answer to your question is, as others have said, that you're telling printf to print a integer number (for example a variable of the type int) whilst passing it a double-precision number (as your variable is of the type double), which is wrong.
Here's a snippet from the printf(3) linux programmer's manual explaining the %d and %f conversion specifiers:
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.
f, F The double argument is rounded and 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 explicitly zero, no decimal-point character appears. If a
decimal point appears, at least one digit appears before it.
To make your current code work, you can do two things. The first alternative has already been suggested - substitute %d with %f.
The other thing you can do is to cast your double to an int, like this:
printf("%d", (int) i);
The more complex answer(addressing why printf acts like it does) was just answered briefly by Jon Purdy. For a more in-depth explanation, have a look at the wikipedia article relating to floating point arithmetic and double precision.
Because i is a double and you tell printf to use it as if it were an int (%d).
#jagan, regarding the sub-question:
What is Left most third byte. Why it is 00000001? Can somebody explain?"
10000000001 is for 1025 in binary format.

How does C Handle Integer Literals with Leading Zeros, and What About atoi?

When you create an integer with leading zeros, how does c handle it? Is it different for different versions of C?
In my case, they just seem to be dropped (but maybe that is what printf does?):
#include <stdio.h>
int main() {
int a = 005;
printf("%i\n", a);
return 0;
}
I know I can use printf to pad with 0s, but I am just wondering how this works.
Leading zeros indicate that the number is expressed in octal, or base 8; thus, 010 = 8. Adding additional leading zeros has no effect; just as you would expect in math, x + 0*8^n = x; there's no change to the value by making its representation longer.
One place you often see this is in UNIX file modes; 0755 actually means 7*8^2+5*8+5 = 493; or with umasks such as 0022 = 2*8+2 = 10.
atoi(nptr) is defined as equivalent to strtol(nptr, (char **) NULL, 10), except that it does not detect errors - as such, atoi() always uses decimal (and thus ignores leading zeros). strtol(nptr, anything, 0) does the following:
The string may begin with an arbitrary
amount of white space (as determined
by isspace(3)) followed by a single
optional '+' or '-' sign. If base is
zero or 16, the string may then
include a "0x" prefix, and the number
will be read in base 16; otherwise, a
zero base is taken as 10 (decimal)
unless the next character is '0', in
which case it is taken as 8 (octal).
So it uses the same rules as the C compiler.
The fact that a leading zero indicates a number is octal is something that's often forgotten. I've seen it cause confusion several times, such as when someone tried to input an IP address using a nice, regular format for the octets:
192.168.010.073
and the parser interpreted the last 2 octets as octal numbers.
The only thing worse than C's unfortunate use of leading zeros to make a number octal is Javascript's handling of leading zeros to sometimes make a number octal (the number is octal if the rest of the digits are OK - less than 8 - decimal otherwise). In Javascript, (017 == 15) but (018 == 18).
I'd rather there be an error; actually I'd rather drop octal literal support altogether. At least use a more in-your-face prefix, like maybe
0t10 (ocTal 8)
0k17 (oKtal 15)
But I'm about 35 years too late with my proposal.
Be careful!
In this statement 005 is an octal constant.
int a = 005;
In this case it doesn't matter because a single digit octal constant has the same value as the equivalent decimal constant but in C: 015 != 15
Whether an integer literal is expressed in octal, decimal or hexadecimal, once it is parsed by the compiler it is just treated as a value. How an integer is output via printf depends only on its type, its value and the format specifiers (and the active locale).
A number with a leading zero means octal encoding in all versions of C. So 011 == 9 == 0x9.
Octal is a numbering system based on 8 (instead of 10 for decimal or 16 for hex). So 011 == 1*8 + 1, 013 == 1*8 + 3, etc.
You should try:
int a = 5;
printf("%03i\n", a);
0 means "pad with zeroes", 3 is the desired length of output.
Edit: Sorry, I've read your question too quickly - now I see you've asked about something completely different. However I'll leave this as is, as it might be helpful for someone else.
A number with leading 0 denoted that the number is an octal number. It's called Integer Literals. You can also use 0b for denoting binary number, for hexadecimal number it is 0x or 0X. You don't need to write any thing for decimal. See the code bellow.
#include<stdio.h>
int main()
{
int binary = 0b10;
int octal=010;
int decimal = 10;
int hexa = 0x10;
printf("%d %d %d %d\n", octal, decimal, hexa, binary);
}
For more information visit tutorialspoint.
Integers don't have "leading zeros" a 5 is a 5, you may write its string representation with leading 0 if you want, for that you have the printf modifiers.
In your particular case, the zeroes are being dropped by printf.
All leading zeroes are stripped out by the compiler except for the initial zero which causes your compiler to treat the integer as octal. For 005, both the octal and decimal representations are the same and should not bother you but still, it's asking for trouble unless you specifically meant the octal representation.
Leading zeroes have to do purely with the string representation of the integer. To print with leading zeroes, use "%03d". This will ensure a field length of 3.
In general, "%<x>d" will print an integer x characters wide and will pad with leading spaces. "%0<x>d" will do the same thing but will pad with leading zeroes.

Why does "%.3i" print leading zeros?

There was a bit of a surprise with some code today. I was compiling it on AIX, with the warning level set to anal to see what rogue issues might be lurking. Something new crawled out of the code.
1540-2837 (W) '0' flag is disregarded when combined with
precision and 'i' printf format.
After looking at the offending line, I put together a little program to reproduce it. Testing it on several platforms showed that it is not AIX specific.
The first printf below mimics what was found in the program.
#include <stdio.h>
int main(void)
{
int x = 3;
printf("Format 0.3i <%0.3i>\n", x); // prints 003, and AIX does a warning
printf("Format .3i <%.3i>\n", x); // prints 003, with no warning
printf("Format 3i <%3i>\n", x); // prints 3, with no warning.
return 0;
}
Normally, if leading zeros were needed, a format of "03i" would do the job nicely.
What does "%.3i" really mean here?
Why does it have the behavior that it does?
.X, where x is a number means "print at least X" digits, so %.3i means print at least 3 digits. If the number is less than 100, it is left padded with zeros.
From a doc on printf
"For integer specifiers (d, i, o, u, x, X): precision specifies the minimum number of digits to be written. If the value to be written is shorter than this number, the result is padded with leading zeros. The value is not truncated even if the result is longer. A precision of 0 means that no character is written for the value 0."
There is another concept, "width" (e.g. "%3i") which causes a certain number of characters to be output (not necessarily digits, and the 0 specified is used to say that those characters should be 0s, as in "003" and not spaces, as in " 3")
From man 3 printf:
If a precision is given with a
numeric conversion (d, i, o, u, x, and
X), the 0 flag is ignored.
The . is specifying the precision and therefore the 0 is ignored. As to the "Why?" of it, you'd have to ask the authors of the C standard :)

Resources