在C语言中将整数转换为二进制

8

我想将整数10转换为二进制数1010。

这段代码试图实现它,但我在strcat()函数上遇到了segfault错误:

int int_to_bin(int k)
{
   char *bin;

   bin = (char *)malloc(sizeof(char));
   while(k>0) {
      strcat(bin, k%2);
      k = k/2;
      bin = (char *)realloc(bin, sizeof(char) * (sizeof(bin)+1));
   }
   bin[sizeof(bin)-1] = '\0';

   return atoi(bin);
}

如何在C语言中将整数转换为二进制?


1
这个操作没有任何分配的理由(更不用说realloc了)。给定类型的大小以位为单位是一个常量,因此只需使用正确大小的缓冲区即可。 - R.. GitHub STOP HELPING ICE
正确的大小当然是sizeof int * CHAR_BIT + 1,以容纳终止空字符。 - Toby Speight
13个回答

19
如果您想将一个数字转换为另一个数字(而不是字符串),并且您可以在小范围内进行操作(对于使用32位整数的实现,范围为0到1023),则无需向解决方案中添加char*
unsigned int_to_int(unsigned k) {
    if (k == 0) return 0;
    if (k == 1) return 1;                       /* optional */
    return (k % 2) + 10 * int_to_int(k / 2);
}

HalosGhost 建议将代码压缩为单行。

unsigned int int_to_int(unsigned int k) {
    return (k == 0 || k == 1 ? k : ((k % 2) + 10 * int_to_int(k / 2)));
}

这比使用字符串简单得多!是你想出来的吗?谢谢! - Hugo
2
@Hugo:很可能是(那是5年前的事了)。无论如何,请注意,对于32位实现,限制为1023int_to_int(1023) == 1111111111;int_to_int(1024) == <UNDEFINED BEHAVIOUR>;)。 - pmg

6
您需要初始化 bin,例如:
bin = malloc(1);
bin[0] = '\0';

或者使用calloc:

bin = calloc(1, 1);

你这里还有一个bug:
 bin = (char *)realloc(bin, sizeof(char) * (sizeof(bin)+1));

this needs to be:

 bin = (char *)realloc(bin, sizeof(char) * (strlen(bin)+1));

即使用strlen而不是sizeof

并且在调用strcat之前应该先增加大小。

并且你没有释放bin,因此存在内存泄漏。

并且你需要将0、1转换为'0'、'1'。

并且你不能将一个字符连接到字符串上。

除此之外,代码很接近,但是代码可能更像这样(警告,未经测试!):

int int_to_bin(int k)
{
   char *bin;
   int tmp;

   bin = calloc(1, 1);
   while (k > 0)
   {
      bin = realloc(bin, strlen(bin) + 2);
      bin[strlen(bin) - 1] = (k % 2) + '0';
      bin[strlen(bin)] = '\0';
      k = k / 2;
   }
   tmp = atoi(bin);
   free(bin);
   return tmp;
}

1
在使用atoi之前释放bin是不太好的做法。你需要使用另一个辅助变量(例如 int tmp=atoi(bin); free(bin); return tmp;)。 - Saytonurn
尽量避免内存堆分配。请看我的回答。 :) - Andy Finkenstadt
感谢您指出的问题。我完全忘记了添加用于将int转换为char的 + '0',这也是为什么它另一种方式也行不通的原因,并且也忘了 strlen()。 - JJRhythm
@Saytonum:感谢你发现了这个问题,也感谢@fazo修复了它。 - Paul R
@Andy:同意 - 我试图尽可能少地修改原始实现来修复它,而不是尝试重新实现更有效的解决方案。我相信有更高效的解决方案,不需要任何动态内存分配或int<->string转换。 - Paul R

5

只需使用itoa将数字转换为字符串,然后使用atoi将其转回十进制。

unsigned int_to_int(unsigned int k) {
    char buffer[65]; /* any number higher than sizeof(unsigned int)*bits_per_byte(8) */
    return atoi( itoa(k, buffer, 2) );
}

1
简单而不是重复造轮子。 - fjardon
1
应该是 return atoi( itoa(k, buffer, 2) ); 才对吧? - peonicles
1
这些不是标准的一部分,因此不能保证它们的存在。 - Hutch Moore

3

嗯,我遇到了同样的问题...所以我找到了这个帖子

我认为来自用户"pmg"的答案并不总是有效。

unsigned int int_to_int(unsigned int k) {
    return (k == 0 || k == 1 ? k : ((k % 2) + 10 * int_to_int(k / 2)));
}

原因:二进制表示被存储为整数形式,这是非常有限的。想象一下将十进制转换为二进制:

 dec 255  -> hex 0xFF  -> bin 0b1111_1111
 dec 1023 -> hex 0x3FF -> bin 0b11_1111_1111

你需要将这个二进制表示存储,就像它是一个十进制数一样。

我认为Andy Finkenstadt的解决方案最接近你所需的。

unsigned int_to_int(unsigned int k) {
    char buffer[65]; // any number higher than sizeof(unsigned int)*bits_per_byte(8)
    return itoa( atoi(k, buffer, 2) );
}

但是如果数字很大,这样做可能就无法正常工作。毕竟,您可能并不真的需要将字符串转换回十进制。这没有太大意义。如果您通常需要二进制数字来用于文本,那么请保留它以字符串格式。只需简单地使用itoa()函数即可。
char buffer[65];
itoa(k, buffer, 2);

1
我知道这已经是3年前的事了,但我现在遇到了同样的问题,并且发现之前的回答中有误导性的信息... - drkovacs
“if ... you can do with a small range” 这句话中有什么误导性的内容? - pmg
@niyasc 八年后,我发现这个答案很有用。 - Matt K

3
整数转二进制的工作解决方案如下。
int main()
{
    int num=241; //Assuming 16 bit integer
    for(int i=15; i>=0; i--) cout<<((num >> i) & 1);
    cout<<endl;
    for(int i=0; i<16; i++) cout<<((num >> i) & 1);
    cout<<endl;
    return 0;
}

您可以根据自己的需求捕获“cout<<”部分。


2
您可以使用这个函数来返回 char* 类型的整数字符串表示形式:
   char* itob(int i) {
      static char bits[8] = {'0','0','0','0','0','0','0','0'};
      int bits_index = 7;
      while ( i > 0 ) {
         bits[bits_index--] = (i & 1) + '0';
         i = ( i >> 1);
      }
      return bits;
   }

这并不是一个完美的实现,但如果你使用简单的printf("%s", itob(170))测试一下,你会得到01010101,我记得它代表了170。再加上atoi(itob(170)),你会得到整数,但它绝对不是170的整数值。


1
甚至可以使用do { bits[bits_index--] = (i & 1) + '0' } while (i>>=1);。此外,由于静态缓冲区的存在,这是不可重入的代码。 - Toby Speight

0
void intToBin(int digit) {
    int b;
    int k = 0;
    char *bits;

    bits= (char *) malloc(sizeof(char));
    printf("intToBin\n");
    while (digit) {
        b = digit % 2;
        digit = digit / 2;
        bits[k] = b;
        k++;

        printf("%d", b);
    }
    printf("\n");
    for (int i = k - 1; i >= 0; i--) {
        printf("%d", bits[i]);

    }

}

请添加一些解释以澄清如何解决问题。 - ekhumoro

0
#define BIT_WIDTH 32

char *IntToBin(unsigned n, char *buffer) {
    char *ptr = buffer + BIT_WIDTH;
    do {
        *(--ptr) = (n & 1) + '0';
        n >>= 1;
    } while(n);
    return ptr;
}

#define TEST 1

#if TEST
    #include <stdio.h>
    
    int main() {
        int n;
        char buff[BIT_WIDTH + 1];
        buff[BIT_WIDTH] = '\0';
        while(scanf("%d", &n) == 1) 
            puts(IntToBin(n, buff));
        return 0;
    }
#endif

0
您可以使用此函数从整数中获取位数组。
    int* num_to_bit(int a, int *len){
        int arrayLen=0,i=1;
        while (i<a){
            arrayLen++;
            i*=2;
        }
        *len=arrayLen;
        int *bits;
        bits=(int*)malloc(arrayLen*sizeof(int));
        arrayLen--;
        while(a>0){
            bits[arrayLen--]=a&1;
            a>>=1;
        }
        return bits;
     }

0

您可以通过以下示例将十进制转换为二进制、十六进制转换为十进制、十六进制转换为二进制等。

将十进制转换为二进制

int convert_to_bin(int number){
    int binary = 0, counter = 0;
    while(number > 0){
        int remainder = number % 2;
        number /= 2;
        binary += pow(10, counter) * remainder;
        counter++;
    }   
}

然后你可以像这样打印二进制等价物:

printf("08%d", convert_to_bin(13)); // 显示前导零


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接