I need to convert 3 digit decimal number to binary using C.
My code:
#include <stdio.h>
#define TWO 2
int main() {
int dec_num; // demical number
int i = 0; // loop cunter
printf("type in 3 digits number to convert to binary\n");
scanf("%d", &dec_num);
while (++i <= 12) {
if (dec_num % TWO != 0) {
printf("1") ;
} else if (dec_num % TWO == 0) {
printf("0");
} else if (dec_num <= 0) {
break;
}
dec_num / TWO;
}
return 0;
}
The problem is that the number doesn't get divided by 2 at the end of the while
loop how can I fix it?
You did not store the value of dec_num
after the division.
dec_num / TWO; //<--------------------
Your while loop condition was also wrong.
while(++i <= 12) //<-------------------
You should perform the division operation until the number is greater than 0
According to the rules of binary to decimal, you should print 1s and 0s in reverse order
. But in your code, you have changed the order. In order to fix that We could store the result in an array
and then we could print the result in reverse order
.
Here is your modified code,
#include <stdio.h>
#define TWO 2
int main()
{
int dec_num; // demical number
int i=0; // loop cunter
printf("type in 3 digits number to convert to binary\n");
int flag = scanf("%d",&dec_num); //<-----check the user input
if(flag!=1)
{
printf("Input is not recognized as an integer");
return 0;
}
int size=0;
int array[120] = {0}; //<-------to store the result
while(dec_num > 0){ //<------- while the number is greater than 0
if(dec_num % TWO !=0){
array[i] = 1;
}
else if(dec_num % TWO ==0){
array[i] = 0;
}
size = ++i; //<------- store the size of result
dec_num = dec_num / TWO; //<------- divide and modify the original number
}
for(i=size-1;i>=0;i--) //<------- print in reverse order
printf("%d",array[i]);
return 0;
}
My solution will assume that the input is a positive number and that maximal decimal 3 digit number can be presented by 10 bits (decimal 999 is binary 1111100111). I will also use the fact that the bit-wise operators are defined by the C standard and should take place. These operations on most of the architectures are very efficient and much faster than /
or %
.
#include <stdio.h>
#define MAX_BIN_DIGITS 10
#define ERR_INVALID_INPUT_VALUE 1
int main(void)
{
int dec_num; // demical input number
int i = MAX_BIN_DIGITS;
int bin_bit;
// storing the result at zero terminated string
char bin_res[MAX_BIN_DIGITS+1] = {0};
printf("Type in 3 digits number to convert to binary:\n");
if (1 != scanf("%d",&dec_num))
{
printf("Error: Invalid input value!");
return ERR_INVALID_INPUT_VALUE;
}
// Checking for 'i' here just to be safe in case of larger input than expected - 4 digits or more
while(i-- && dec_num)
{
bin_bit = dec_num & 1; // get the LSB
dec_num >>= 1; // remove the LSB from 'dec_num'
bin_res[i] = '0' + bin_bit; // store the LSB at the end as a char
}
// Print the array starting from the most significant bit which is '1'
// NOTE: Need to take care of special case when the input is '0', then 'i'
// will be equal to 'MAX_BIN_DIGITS-1'.
printf("%s\n", (i != MAX_BIN_DIGITS-1) ? &(bin_res[i+1]) ? "0");
return 0;
}
There are multiple problems in your code:
scanf()
: you get undefined behavior if the user fails to input characters that can be converted to an integer. num % TWO
is either 0 or 1, the second test is redundant and the third test is never executed, so the loop fails to detect proper termination condition. dec_num / TWO;
does not update dev_num
, so your loop just keeps printing the least significant bit (and the test while (++i <= 12)
is indeed necessary for the loop to stop). #define TWO 2
is not strictly speaking a mistake, but does not improve code readability or safety. Local coding rules might bar you from using non trivial numeric constants in the code: such a rule seems counter productive in this particular case. demical number
is cute and loop cunter
is intriguing. Here is a corrected version of your code, using your algorithm, to illustrate the unexpected output (last significant bit to most significant bit):
#include <stdio.h>
int main() {
int dec_num; // decimal number
printf("type in a 3 digit number to convert to binary\n");
if (scanf("%d", &dec_num) != 1) {
printf("invalid input\n");
return 1;
}
if (dec_num < 0 || dec_num > 999) {
printf("invalid value: must have at most 3 digits\n");
return 1;
}
for (;;) {
if (dec_num % 2 != 0) {
printf("1");
} else {
printf("0");
}
dec_num = dec_num / 2;
if (dec_num == 0)
break;
}
printf("\n");
return 0;
}
Here is a recursive version that outputs the bits in the proper order:
#include <stdio.h>
void output_binary(int num) {
if (num > 1)
output_binary(num / 2);
printf("%d", num % 2);
}
int main() {
int dec_num; // decimal number
printf("type in a 3 digit number to convert to binary\n");
if (scanf("%d", &dec_num) != 1) {
printf("invalid input\n");
return 1;
}
if (dec_num < 0 || dec_num > 999) {
printf("invalid value: must have at most 3 digits\n");
return 1;
}
output_binary(dec_num);
printf("\n");
return 0;
}
While you already have a valid answer correcting the failure to update dec_num
following division and valid recursive methods provided by others, it is unclear whether you intend to allow entry of negative 3-digit values as well as positive values. An implementation that determines the size of the type and then shifts by one over each of the bits can provide a simple solution that will handle both positive and negative values.
For example the conversion part of the code shifting by 1
for each bit (indexed 31 -> 0
) could be as simple as:
int main (void) {
int decnum = 0; /* user input number */
unsigned remain = 0; /* remainder after shift */
size_t nbits = sizeof decnum * CHAR_BIT; /* number of bits for type */
/* read decnum here */
printf ("decimal: %d\nbinary : ", decnum); /* output value */
while (nbits--) { /* write bits 31->0 while 1 bits remain */
if ((remain = decnum >> nbits)) /* shift saving shifted value */
putchar ((remain & 1) ? '1' : '0'); /* bit 0/1 output '0'/'1' */
}
putchar ('\n'); /* tidy up with newline */
}
(note: a simple ternary
operator is used to determine whether to output '1'
or '0'
)
The bigger part of your problem is the your failure to check the return of scanf
. This is an open invitation for Undefined Behavior . Regardless of what function you use for user-input , you must validate that input succeeded before proceeding further. Otherwise you will invoke undefined behavior when you attempt to access an indeterminate value.
When using scanf
in order to require valid input, you must handle three cases each time (1) did the user cancel input by pressing Ctrl+d generating a manual EOF
? ( Ctrl+z on windows), (2) did a matching or input failure occur? and (3) the good input case. Then, as is your case, you must further validate the input was in the proper range of values (a 3 digit number in your case). Additionally, to require valid input, you must handle any character that remains unread in the input buffer (as is the case for a matching failure, or if the user slipped and typed additional characters after the integer value.
Now it is completely fine to simply validate the input and return
on an invalid input regardless of what caused the failure, but to require valid input it is up to you to handle all three cases, check that the input was within the valid range (and even then remove the trailing '\\n'
left by scanf
preparing the input-buffer for whatever additional input may be taken later in your code.
Many times that will require more code than your actual calculation does, but it is critical. For instance in your case, if you wanted to require the user to enter valid input, you could replace the /* read decnum here */
with something similar to:
for (;;) { /* loop continually until valid input or canceled */
int rtn; /* variable to hold scanf return */
fputs ("enter 3 digit integer: ", stdout); /* prompt */
rtn = scanf ("%d", &decnum); /* read value, saving return */
if (rtn == EOF) { /* handle manual EOF cancelation */
fputs ("(user canceled input)\n", stderr);
return 1;
}
if (rtn == 0) { /* handle input failure */
empty_stdin(); /* always empty input buffer */
fputs (" error: invalid integer input.\n", stderr);
} /* validate 3 digit poisitive (or negative) number */
else if (decnum < -999 || (decnum > -100 && decnum < 100)
|| decnum > 999) {
empty_stdin();
fputs (" error: not a 3 digit number.\n", stderr);
}
else { /* handle good input case (break loop) */
empty_stdin();
break;
}
}
note: the helper function empty_stdin()
. That can be implemented with getchar()
to read and discard any characters causing problems, eg
void empty_stdin (void) /* helper function to empty stdin after bad input */
{ /* (as well as the trailing '\n' after good input) */
int c = getchar();
while (c != '\n' && c != EOF)
c = getchar();
}
Putting it altogether, you could do something like the following:
#include <stdio.h>
#include <limits.h> /* for CHAR_BIT */
void empty_stdin (void) /* helper function to empty stdin after bad input */
{ /* (as well as the trailing '\n' after good input) */
int c = getchar();
while (c != '\n' && c != EOF)
c = getchar();
}
int main (void) {
int decnum = 0; /* user input number */
unsigned remain = 0; /* remainder after shift */
size_t nbits = sizeof decnum * CHAR_BIT; /* number of bits for type */
for (;;) { /* loop continually until valid input or canceled */
int rtn; /* variable to hold scanf return */
fputs ("enter 3 digit integer: ", stdout); /* prompt */
rtn = scanf ("%d", &decnum); /* read value, saving return */
if (rtn == EOF) { /* handle manual EOF cancelation */
fputs ("(user canceled input)\n", stderr);
return 1;
}
if (rtn == 0) { /* handle input failure */
empty_stdin(); /* always empty input buffer */
fputs (" error: invalid integer input.\n", stderr);
} /* validate 3 digit poisitive (or negative) number */
else if (decnum < -999 || (decnum > -100 && decnum < 100)
|| decnum > 999) {
empty_stdin();
fputs (" error: not a 3 digit number.\n", stderr);
}
else { /* handle good input case (break loop) */
empty_stdin();
break;
}
}
printf ("decimal: %d\nbinary : ", decnum); /* output value */
while (nbits--) { /* write bits 31->0 while 1 bits remain */
if ((remain = decnum >> nbits)) /* shift saving shifted value */
putchar ((remain & 1) ? '1' : '0'); /* bit 0/1 output '0'/'1' */
}
putchar ('\n'); /* tidy up with newline */
}
Example Use/Output
$ ./bin/prnbin3digit
enter 3 digit integer: why?
error: invalid integer input.
enter 3 digit integer: -75
error: not a 3 digit number.
enter 3 digit integer: 1024
error: not a 3 digit number.
enter 3 digit integer: 127 and more junk
decimal: 127
binary : 1111111
Or the case with a negative value:
$ ./bin/prnbin3digit
enter 3 digit integer: -127
decimal: -127
binary : 11111111111111111111111110000001
Or the case where the user cancels input:
$ ./bin/prnbin3digit
enter 3 digit integer: (user canceled input)
While this ended up being longer than what a simple right-shift
implementation of the conversion would have been, it is worth building good user-input habits now to avoid untold problems later. Look things over and let me know if you have further questions.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.