I am trying to print binary numbers in C language. I'm having a problem with binary numbers starting with 0. When you try to keep it in the arrays and try to print it, random numbers come up, when you get input with scanf, the leading zero of the number disappears.
What should I do in this situation? Thank you in advance for your help.
int main(){
int binarys[3] ={01001001, 01100110, 00100000};
size_t i;
for(i=0; i<3; i )
{
printf("%d\n", binarys[i]);
}
int binary;
printf("Enter a binary: ");
scanf("%d", &binary);
printf("%d", binary);
}
Output:
262657
294984
32768
Enter a binary: 01001001
1001001
CodePudding user response:
I'm having a problem with binary numbers starting with 0
Integer constants starting with 0
are not binary but octal.
If you have a compiler that offers the 0b
prefix as an extension (or come from the future where this has been standardized) and want to declare an integer with the value 32, in base two for whatever reason, write 0b00100000
. It'll still have exactly the same contents as if you just wrote 32
though, because a base is how a number is represented, and doesn't affect its value.
when you get input with scanf,
The scanf
function does not have a conversion specifier for binary, and %d
explicitly means decimal, ie, base 10.
If you want to scan numbers written in binary, you'll need to read a string, confirm it's only ones and zeroes, and convert it yourself (ie, using strtol
like strol(str, &end, 2)
).
... the leading zero of the number disappears
Leading zeroes are not printed by default.
Again, printf
does not have a binary conversion specifier anyway, but if you want to print leading zeroes, you need both to set a field width and to request zero padding, like d
.
If you want to print numbers in binary, you need to convert those to a string yourself first as well.
CodePudding user response:
Integer literals:
In C and C , an integer literal starting with a 0
means it is represented in octal (base 8).
The array of int
s you have initialized therefore contains the octal values of 1001001, 1100110, 100000, which are 262657, 294984, 32768 respectively.
Binary literals are availbale in C since C 14. C is supposed to support it in C23 (see: https://en.cppreference.com/w/c/language/integer_constant).
In this code example:
int main()
{
int a = 010;
printf("%d\n", a);
int b = 0b10;
printf("%d\n", b);
}
The following will be printed (C 14):
8
2
Because 8 is the decimal value for the octal 10
, and 2 is the decimal value for the binary 10
.
The issue with scanf
:
scanf
parses the entered value as a decimal int
(since you specified the %d
format specifier). It does not apply the language literal rules. Therefore the leading 0 that has no mathematical meaning is ignored. You entered 01001001
, which is parsed as the decimal int
with value 1001001 and that is what you see in the printf
that follows (which again uses the %d
format specifier).
CodePudding user response:
C does not (yet) support binary integer constants or scanf/print conversion specifiers for binary. It has been proposed for the upcoming C standard "C23". Until then, 0b
prefix and %b
conversion specifiers may be supported by some compilers as non-standard extensions (0b
very likely, %b
not so likely).
Numbers starting with 0
are actually octal integer constants. Either way, printing/reading some 01001001
integer constant using %d
is nonsense.
With current standard C, you could cook up a compile-time conversion using a bunch of admittedly ugly macros:
#include <stdio.h>
#define STATIC_ASSERT(expr) (int [expr]){0}
#define STR_TO_BIN(str) ( (str[0]-'0') * 128 \
(str[1]-'0') * 64 \
(str[2]-'0') * 32 \
(str[3]-'0') * 16 \
(str[4]-'0') * 8 \
(str[5]-'0') * 4 \
(str[6]-'0') * 2 \
(str[7]-'0') * 1 )
#define BINARIFY(n) (STATIC_ASSERT(sizeof(#n)==9), STR_TO_BIN(#n))
int main(){
int binaries[3] ={BINARIFY(01001001), BINARIFY(01100110), BINARIFY(00100000)};
for(size_t i=0; i<3; i )
{
printf("%d\n", binaries[i]);
}
}
(The "poor man's static assert" protects against array out of bounds access but not against incorrect input formats.)