[英]Converting 3 digit decimal number to binary (C)
我需要使用C将3位数的十进制数转换为二进制。
我的代码:
#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;
}
问题是,在while
循环结束时,数字没有被2除以该怎么解决?
dec_num
后,您没有存储dec_num
的值。
dec_num / TWO; //<--------------------
您的while循环条件也错了。
while(++i <= 12) //<-------------------
您应该执行除法运算,直到数字大于0
根据二进制到十进制的规则,应该以reverse order
打印1和0。 但是在您的代码中,您更改了顺序。 为了解决这个问题,我们可以将结果存储在array
,然后可以以reverse order
打印结果。
这是您修改的代码,
#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;
}
我的解决方案将假设输入为正数,并且最大十进制3位数字可以由10位表示(十进制999为二进制1111100111)。 我还将使用以下事实:按位运算符由C标准定义并且应该发生。 在大多数体系结构上的这些操作非常高效,并且比/
或%
快得多。
#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;
}
您的代码中存在多个问题:
scanf()
的返回值:如果用户未能输入可以转换为整数的字符,则会得到未定义的行为。 num % TWO
为0或1,第二个测试是冗余的,第三个测试从未执行,因此循环无法检测到正确的终止条件。 dec_num / TWO;
不会更新dev_num
,因此您的循环只会继续输出最低有效位( while (++i <= 12)
停止循环确实需要测试while (++i <= 12)
)。 #define TWO 2
并不是严格意义上的错误,但不能提高代码的可读性或安全性。 本地编码规则可能会禁止您在代码中使用非平凡的数字常量:在这种特殊情况下,这样的规则似乎适得其反。 demical number
很可爱, loop cunter
器很有趣。 这是使用您的算法的经过纠正的代码版本,用于说明意外的输出(最后有效位到最高有效位):
#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;
}
这是递归版本,以正确的顺序输出位:
#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;
}
尽管您已经有了一个有效的答案,可以纠正除法dec_num
后无法更新dec_num
以及其他人提供的有效递归方法,但您是否打算允许输入负的 3位数和正值尚不清楚。 确定类型的大小,然后在每个位上移一个的实现可以提供一种简单的解决方案,该方案将处理正值和负值。
例如,对于每个位(索引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 */
}
(注意:使用简单的ternary
运算符来确定是输出'1'
还是'0'
)
问题的最大部分是您无法检查 scanf
的返回 。 这是未定义行为的公开邀请。 无论用户输入使用什么功能,都必须先验证输入是否成功,然后再继续操作。 否则,当您尝试访问不确定的值时,将调用未定义的行为。
使用scanf
要求有效输入时,每次必须处理三种情况(1)用户是否通过按Ctrl + d生成手动EOF
取消输入? (在Windows上为Ctrl + z ),(2)是否发生匹配或输入失败? (3)输入情况良好。 然后,根据您的情况,您必须进一步验证输入是否在适当的值范围内(在您的情况下为3位数字)。 此外,要要求有效的输入,您必须处理输入缓冲区中任何未读的字符(如匹配失败或用户在整数值后滑动并键入其他字符的情况)。
现在完全可以简单地验证输入并return
无效输入,而不管是由什么原因引起的故障,但是要要求输入有效,则由您来处理所有三种情况,请检查输入是否在有效范围内(并且即使随后删除scanf
留下的尾部'\\n'
,也要为以后在代码中可能需要的其他输入准备输入缓冲区。
很多时候需要比实际计算更多的代码,但这很关键。 例如,在您的情况下,如果您想要求用户输入有效的输入,则可以用类似于以下内容的/* 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;
}
}
注意:辅助函数empty_stdin()
。 可以使用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();
}
综上所述,您可以执行以下操作:
#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 */
}
使用/输出示例
$ ./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
或带有负值的情况:
$ ./bin/prnbin3digit
enter 3 digit integer: -127
decimal: -127
binary : 11111111111111111111111110000001
或用户取消输入的情况:
$ ./bin/prnbin3digit
enter 3 digit integer: (user canceled input)
尽管这样做的时间比转换的简单right-shift
实施要长,但是现在值得养成良好的用户输入习惯,以免以后出现无法解决的问题。 仔细检查一下,如果您还有其他问题,请告诉我。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.