[英]Converting 3 digit decimal number to binary (C)
I need to convert 3 digit decimal number to binary using C. 我需要使用C将3位数的十进制数转换为二进制。
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? 问题是,在while
循环结束时,数字没有被2除以该怎么解决?
You did not store the value of dec_num
after the division. dec_num
后,您没有存储dec_num
的值。
dec_num / TWO; //<--------------------
Your while loop condition was also wrong. 您的while循环条件也错了。
while(++i <= 12) //<-------------------
You should perform the division operation until the number is greater than 0 您应该执行除法运算,直到数字大于0
According to the rules of binary to decimal, you should print 1s and 0s in reverse order
. 根据二进制到十进制的规则,应该以reverse order
打印1和0。 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
. 为了解决这个问题,我们可以将结果存储在array
,然后可以以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). 我的解决方案将假设输入为正数,并且最大十进制3位数字可以由10位表示(十进制999为二进制1111100111)。 I will also use the fact that the bit-wise operators are defined by the C standard and should take place. 我还将使用以下事实:按位运算符由C标准定义并且应该发生。 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. 您不测试scanf()
的返回值:如果用户未能输入可以转换为整数的字符,则会得到未定义的行为。 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. 测试不一致: num % TWO
为0或1,第二个测试是冗余的,第三个测试从未执行,因此循环无法检测到正确的终止条件。 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). 不会更新dev_num
,因此您的循环只会继续输出最低有效位( while (++i <= 12)
停止循环确实需要测试while (++i <= 12)
)。 #define TWO 2
is not strictly speaking a mistake, but does not improve code readability or safety. #define TWO 2
并不是严格意义上的错误,但不能提高代码的可读性或安全性。 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. 谨防错别字: demical number
很可爱, loop cunter
器很有趣。 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. 尽管您已经有了一个有效的答案,可以纠正除法dec_num
后无法更新dec_num
以及其他人提供的有效递归方法,但您是否打算允许输入负的 3位数和正值尚不清楚。 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: 例如,对于每个位(索引31 -> 0
),将代码移位1
的转换部分可能很简单:
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'
) (注意:使用简单的ternary
运算符来确定是输出'1'
还是'0'
)
The bigger part of your problem is the your failure to check the return of scanf
. 问题的最大部分是您无法检查 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
? 使用scanf
要求有效输入时,每次必须处理三种情况(1)用户是否通过按Ctrl + d生成手动EOF
取消输入? ( Ctrl+z on windows), (2) did a matching or input failure occur? (在Windows上为Ctrl + z ),(2)是否发生匹配或输入失败? and (3) the good input case. (3)输入情况良好。 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). 然后,根据您的情况,您必须进一步验证输入是否在适当的值范围内(在您的情况下为3位数字)。 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. 现在完全可以简单地验证输入并return
无效输入,而不管是由什么原因引起的故障,但是要要求输入有效,则由您来处理所有三种情况,请检查输入是否在有效范围内(并且即使随后删除scanf
留下的尾部'\\n'
,也要为以后在代码中可能需要的其他输入准备输入缓冲区。
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: 例如,在您的情况下,如果您想要求用户输入有效的输入,则可以用类似于以下内容的/* read decnum here */
代替:
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()
. 注意:辅助函数empty_stdin()
。 That can be implemented with getchar()
to read and discard any characters causing problems, eg 可以使用getchar()
来实现,以读取和丢弃引起问题的任何字符,例如
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. 尽管这样做的时间比转换的简单right-shift
实施要长,但是现在值得养成良好的用户输入习惯,以免以后出现无法解决的问题。 Look things over and let me know if you have further questions. 仔细检查一下,如果您还有其他问题,请告诉我。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.