我需要使用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,我该如何解决?
答案 0 :(得分:2)
除法后,您没有存储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;
}
答案 1 :(得分:1)
我的解决方案将假定输入为正数,并且最大十进制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;
}
答案 2 :(得分:1)
您的代码中存在多个问题:
scanf()
的返回值:如果用户未能输入可以转换为整数的字符,则会出现不确定的行为。num % TWO
是0或1,第二个测试是冗余的,而第三个测试则从不执行,因此循环无法检测到正确的终止条件。dec_num / TWO;
不会更新dev_num
,因此您的循环只会继续打印最低有效位(并且测试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;
}
答案 3 :(得分:0)
虽然您已经有了一个有效的答案,可以纠正除法后无法更新dec_num
的失败以及其他人提供的有效递归方法,但您是否打算允许输入负数尚不清楚3-数字值和正值。确定类型大小然后在每个位上移一个值的实现可以提供一种既可以处理正值也可以处理负值的简单解决方案。
例如,对于每个位(索引为1
)移位31 -> 0
的代码转换部分可以很简单:
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
的退货。这是未定义行为的公开邀请。无论您为 user-input 使用什么功能,都必须先验证该输入是否成功,然后再继续操作。否则,当您尝试访问不确定的值时,您将调用未定义的行为。
使用scanf
来要求有效输入时,每次(1)用户按下 Ctrl + d 生成手册EOF
? (在Windows上为 Ctrl + z ),(2)是否发生了 matching 或 input 失败? (3)输入情况良好。然后,根据您的情况,您必须进一步验证,输入的值在适当的范围内(本例中为3位数字)。此外,要要求有效输入,您必须处理输入缓冲区中仍未读的任何字符(如 matching 失败的情况,或用户在该整数值后滑动并键入其他字符。
现在完全可以简单地验证输入,并在无效输入上return
进行验证,而不管是什么原因导致失败,但是需要有效输入则完全由您来处理在三种情况下,请检查输入内容是否在有效范围内(甚至删除'\n'
留下的结尾scanf
,为以后在代码中可能要使用的其他输入准备输入缓冲区。>
很多时候需要比实际计算更多的代码,但这很关键。例如,在您的情况下,如果您想要求输入用户的有效输入,则可以将/* 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
实现的时间长,但是现在值得养成良好的用户输入习惯,以避免以后出现无法解决的问题。仔细研究一下,如果您还有其他问题,请告诉我。