【问题标题】:Display the binary representation of a number in C? [duplicate]在 C 中显示数字的二进制表示? [复制]
【发布时间】:2010-10-16 13:04:05
【问题描述】:

可能重复:
Is there a printf converter to print in binary format?

还在学习C,我想知道:

给定一个数字,是否可以执行以下操作?

char a = 5;
printf("binary representation of a = %b",a);
> 101

或者我是否必须编写自己的方法来进行二进制转换?

【问题讨论】:

    标签: c binary printf representation


    【解决方案1】:

    没有直接的方法(即使用printf 或其他标准库函数)来打印它。您必须编写自己的函数。

    /* This code has an obvious bug and another non-obvious one :) */
    void printbits(unsigned char v) {
       for (; v; v >>= 1) putchar('0' + (v & 1));
    }
    

    如果您使用的是终端,您可以使用控制代码以自然顺序打印出字节:

    void printbits(unsigned char v) {
        printf("%*s", (int)ceil(log2(v)) + 1, ""); 
        for (; v; v >>= 1) printf("\x1b[2D%c",'0' + (v & 1));
    }
    

    【讨论】:

    • 不错的小技巧。不可读的代码 FTW!
    • @Chris Lutz:实际上,这很简单 :-)
    • @Chris Lutz:我非常同意。该函数命名良好,并且以线性方式清晰地编写。每个陈述都简单明了。
    • 我投了赞成票,而且确实喜欢这个解决方案。我有时也有点讽刺。抱歉,好像我认为这很糟糕。如果您知道按位运算,我认为它的可读性很高。不幸的是,很多人没有。 (另外,>>= 和
    • 明显的错误 - 它以相反的顺序打印位。不明显的错误 - 对于 v = 0,它不打印任何内容。
    【解决方案2】:

    使用查找表,例如:

    char *table[16] = {"0000", "0001", .... "1111"};
    

    然后像这样打印每个半字节

    printf("%s%s", table[a / 0x10], table[a % 0x10]);
    

    当然你可以只使用一张桌子,但它会稍微快一点而且太大。

    【讨论】:

      【解决方案3】:
      #include<iostream>
      #include<conio.h>
      #include<stdlib.h>
      using namespace std;
      void displayBinary(int n)
      {
             char bistr[1000];
             itoa(n,bistr,2);       //2 means binary u can convert n upto base 36
             printf("%s",bistr);
      
      }
      
      int main()
      {
          int n;
          cin>>n;
          displayBinary(n);
          getch();
          return 0;
      }
      

      【讨论】:

        【解决方案4】:

        此代码应能满足您最多 64 位的需求。

        
        
        char* pBinFill(long int x,char *so, char fillChar); // version with fill
        char* pBin(long int x, char *so);                    // version without fill
        #define width 64
        
        char* pBin(long int x,char *so)
        {
         char s[width+1];
         int    i=width;
         s[i--]=0x00;   // terminate string
         do
         { // fill in array from right to left
          s[i--]=(x & 1) ? '1':'0';  // determine bit
          x>>=1;  // shift right 1 bit
         } while( x &gt 0);
         i++;   // point to last valid character
         sprintf(so,"%s",s+i); // stick it in the temp string string
         return so;
        }
        
        
        char* pBinFill(long int x,char *so, char fillChar)
        { // fill in array from right to left
         char s[width+1];
         int    i=width;
         s[i--]=0x00;   // terminate string
         do
         {
          s[i--]=(x & 1) ? '1':'0';
          x>>=1;  // shift right 1 bit
         } while( x > 0);
         while(i>=0) s[i--]=fillChar;    // fill with fillChar 
         sprintf(so,"%s",s);
         return so;
        }
        
        
        void test()
        {
         char so[width+1]; // working buffer for pBin
         long int   val=1;
         do
         {
           printf("%ld =\t\t%#lx =\t\t0b%s\n",val,val,pBinFill(val,so,0));
           val*=11; // generate test data
         } while (val < 100000000);
        }
        
        Output:
        00000001 = 0x000001 =   0b00000000000000000000000000000001
        00000011 = 0x00000b =   0b00000000000000000000000000001011
        00000121 = 0x000079 =   0b00000000000000000000000001111001
        00001331 = 0x000533 =   0b00000000000000000000010100110011
        00014641 = 0x003931 =   0b00000000000000000011100100110001
        00161051 = 0x02751b =   0b00000000000000100111010100011011
        01771561 = 0x1b0829 =   0b00000000000110110000100000101001
        19487171 = 0x12959c3 =  0b00000001001010010101100111000011
        

        【讨论】:

          【解决方案5】:

          是的(自己写),类似下面的完整函数。

          #include <stdio.h> /* only needed for the printf() in main(). */
          #include <string.h>
          
          /* Create a string of binary digits based on the input value.
             Input:
                 val:  value to convert.
                 buff: buffer to write to must be >= sz+1 chars.
                 sz:   size of buffer.
             Returns address of string or NULL if not enough space provided.
          */
          static char *binrep (unsigned int val, char *buff, int sz) {
              char *pbuff = buff;
          
              /* Must be able to store one character at least. */
              if (sz < 1) return NULL;
          
              /* Special case for zero to ensure some output. */
              if (val == 0) {
                  *pbuff++ = '0';
                  *pbuff = '\0';
                  return buff;
              }
          
              /* Work from the end of the buffer back. */
              pbuff += sz;
              *pbuff-- = '\0';
          
              /* For each bit (going backwards) store character. */
              while (val != 0) {
                  if (sz-- == 0) return NULL;
                  *pbuff-- = ((val & 1) == 1) ? '1' : '0';
          
                  /* Get next bit. */
                  val >>= 1;
              }
              return pbuff+1;
          }
          

          将此 main 添加到它的末尾以查看它的运行情况:

          #define SZ 32
          int main(int argc, char *argv[]) {
              int i;
              int n;
              char buff[SZ+1];
          
              /* Process all arguments, outputting their binary. */
              for (i = 1; i < argc; i++) {
                  n = atoi (argv[i]);
                  printf("[%3d] %9d -> %s (from '%s')\n", i, n,
                      binrep(n,buff,SZ), argv[i]);
              }
          
              return 0;
          }
          

          "progname 0 7 12 52 123" 运行得到:

          [  1]         0 -> 0 (from '0')
          [  2]         7 -> 111 (from '7')
          [  3]        12 -> 1100 (from '12')
          [  4]        52 -> 110100 (from '52')
          [  5]       123 -> 1111011 (from '123')
          

          【讨论】:

          • 如果 binrep() 函数没有为它正在打印的值提供足够的空间,我会看到缓冲区下溢。而且,从痛苦(但很久以前)的经验来看,在数组前面写的东西可能真的很难调试!
          • 是的,那会很麻烦 - 如果你的 int 超过 32 位,你必须确保你增加 SZ 以适应。
          • 已修复以防止缓冲区溢出。
          • 引用:“buff:要写入的缓冲区必须 >= sz+1 个字符。” - sz 是缓冲区的大小,不包括终止的 null。
          • @Pax:哦,好吧......我会删除我的评论。当看到一个函数使用一个与简单 sizeof 不兼容的字符串大小参数时,我会感到不安;在我看来,要求我记住加或减 1 并不酷。
          【解决方案6】:

          基于dirkgently's answer,但修复了他的两个bug,并且总是打印固定的位数:

          void printbits(unsigned char v) {
            int i; // for C89 compatability
            for(i = 7; i >= 0; i--) putchar('0' + ((v >> i) & 1));
          }
          

          【讨论】:

          • 锦上添花,您还可以将 i = 7 替换为 (sizeof(v)*8)-1
          • 如果我能找到一种方法让函数接受任何类型的参数,而不仅仅是一个无符号字符,我会这样做。我尝试使用 void 指针,但出现错误。不过,我需要在某个时候进行更多研究。
          • 这对我有用:char* printbits(int v) { for(int i = (sizeof(v)*8)-1; i >= 0; i--) putchar('0 ' + ((v >> i) & 1)); }
          • 有没有办法让它返回 char*?
          • @David - 当然有。谷歌搜索与此相关的其他问题。 (或者问你自己的,但我敢打赌它是重复的。)你可能需要使用malloc
          【解决方案7】:

          C 语言中没有直接的格式说明符。虽然我写了这个快速的python sn-p来帮助你一步步理解这个过程来滚动你自己的。

          #!/usr/bin/python
          
          dec = input("Enter a decimal number to convert: ")
          base = 2
          solution = ""
          
          while dec >= base:
              solution = str(dec%base) + solution
              dec = dec/base
          if dec > 0:
              solution = str(dec) + solution
          
          print solution
          

          解释:

          dec = input("输入要转换的十进制数:") - 提示用户输入数字(例如在 C 中通过 scanf 有多种方法)

          base = 2 - 指定我们的基数为 2(二进制)

          solution = "" - 创建一个空字符串,我们将在其中连接我们的解决方案

          while dec >= base: - 当我们的数字大于输入的基数时

          solution = str(dec%base) + solution - 获取数字的模数,并将其添加到字符串的开头(我们必须使用除法从右到左添加数字和余数法)。 str() 函数将运算结果转换为字符串。在没有类型转换的情况下,你不能在 python 中将整数与字符串连接起来。

          dec = dec/base - 将十进制数除以基数,准备取下一个模数

          如果 dec > 0: solution = str(dec) + solution - 如果有任何剩余,请将其添加到开头(如果有,则为 1)

          打印解决方案 - 打印最终数字

          【讨论】:

          • 你错过了输入为0的情况,在这种情况下不会打印任何内容。
          • 我认为没有人会费心将 0 放入转换器,因为答案很明显,但请选择您选择的修复程序。脚本顶部的 if 语句以及 sys.exit 或检查底部解决方案变量的值。
          【解决方案8】:

          您必须编写自己的转换。格式说明符仅支持十进制、十六进制和八进制数字。

          【讨论】:

            猜你喜欢
            • 2013-05-07
            • 2016-02-20
            • 2014-12-05
            • 2012-01-24
            • 2013-12-11
            • 2012-03-31
            • 1970-01-01
            • 2019-07-24
            相关资源
            最近更新 更多