繁体   English   中英

将3位数的十进制数字转换为二进制(C)

[英]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()的返回值:如果用户未能输入可以转换为整数的字符,则会得到未定义的行为。
  • 您无需测试该数字是否确实最多包含3位数字。
  • 您最多可以迭代12次,但是10足够了,因为2 10 = 1024,它大于任何3位数字
  • 事实上,甚至没有必要限制迭代次数,因为您可以在迭代次数降至0时停止。
  • 测试不一致: 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM