我刚从C开始,我正在尝试创建一个程序,该程序使用此方法(从 indepth.dev 开始(获取数字并将其转换为二进制:
要将整数转换为二进制,请从有问题的整数开始,然后将其除以 2,注意商和余数。继续将商除以 2,直到得到零商。然后只需以相反的顺序写出其余部分。 (...) 现在,我们只需要以相反的顺序写出余数 — 1100。因此,十进制系统中的 12 在二进制中表示为 1100。
我正在尝试使数组的大小动态。来自Python这有点令人困惑,因为在Python中,你可以附加到列表中。
这是我到目前为止的代码:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main()
{
int *ptr, n, i;
ptr = (int*)malloc(1 * sizeof(int));
printf("Enter a number to convert: ");
scanf("%d", &n);
for (i = 0; n>0; i++)
{
ptr = realloc(ptr, i * sizeof(int));
ptr[i] = n % 2;
n = n/2;
}
for(i=i-1; i>= 0; i--)
{
printf("%d", ptr[i]);
}
free(ptr);
return 0;
}
当我运行程序并输入一个数字时,它不会输出任何内容。如果我对固定数组大小做同样的事情,它可以工作。为什么会这样?
问题出在这几行:
for (i = 0; n>0; i++)
{
ptr = realloc(ptr, i * sizeof(int));
ptr[i] = n % 2;
n = n/2;
}
您正在重新分配一个每次都能容纳i
整数的数组,但是您最终会在索引i
处写入。一个保存整数i
数组的索引从0
到i - 1
,因此你写的是在数组的末尾。这会导致未定义的行为。
最简单的解决方法是从i = 1
开始并写入ptr[i - 1]
:
for (i = 1; n > 0; i++)
{
ptr = realloc(ptr, i * sizeof(int));
ptr[i - 1] = n % 2;
n = n/2;
}
更简单的方法是使用固定大小的数组。您已经知道int
的长度为8*sizeof(int)
位,因此这是您需要的最大值。此外,您可能不需要使用有符号整数,因为它们可能会导致负值出现问题(因此您可以使用unsigned
(。
编辑:我说8 * sizeof(int)
因为sizeof
运算符返回类型的大小(在本例中为int
(以字节为单位。一个字节是 8 位,所以我把它乘以 8 得到以位为单位的大小。我在这里说8
,但是使用CHAR_BIT
(从limits.h
开始(会更好,因为 C 中的"字节"可以使用超过 8 位表示,在这种情况下,CHAR_BIT
每字节拥有正确的位数。我不知道有任何 C 实现的值与8
forCHAR_BIT
不同,但这仍然是正确的方法。我更新了下面的代码以使用CHAR_BIT
而不是8
.
#include <stdio.h>
#include <limits.h>
#define N_BITS CHAR_BIT * sizeof(unsigned)
int main(void) {
unsigned digits[N_BITS] = {0}; // Start with an array filled with zeroes.
unsigned n;
int i;
printf("Enter a number to convert: ");
scanf("%u", &n);
// Calculate binary digits.
for (i = 0; n > 0; i++) {
digits[i] = n % 2;
n /= 2;
}
// Skip leading zeroes.
while (digits[i] == 0)
i--;
// Print binary digits in reverse order.
for(; i >= 0; i--)
printf("%u", digits[i]);
// Final newline.
putchar('n');
return 0;
}
奖金:
#include <stdio.h>
int main(void) {
int i = 8 * sizeof(unsigned);
unsigned n;
printf("Enter a number to convert: ");
scanf("%u", &n);
while (i--)
putchar('0' + ((n >> i) & 1));
putchar('n');
return 0;
}
您分配的内存不足。如果sizeof( int )
等于4
则二进制位数可以等于32
(sizeof( int ) * CHAR_BIT
(。
而且没有必要使用realloc。
而且这句话
ptr = realloc(ptr, i * sizeof(int));
当循环中的i
等于 0 时,分配大小为零的内存。您可能不会写入这样的记忆。
此外,还应使用无符号 int 类型的对象。
这是一个演示程序。
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
int main(void)
{
unsigned int Base = 2;
int *ptr = malloc( CHAR_BIT * sizeof( unsigned int ) );
printf( "Enter a number to convert: " );
unsigned int x = 0;
scanf( "%u", &x );
size_t n = 0;
do
{
ptr[n++] = x % Base;
} while ( x /= Base );
while ( n-- )
{
printf( "%u", ptr[n] );
}
putchar( 'n' );
free( ptr );
return 0;
}
它的输出可能看起来像
Enter a number to convert: 12
1100
如果要使用realloc
则代码可能如下所示
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
int main(void)
{
unsigned int Base = 2;
int *ptr = NULL;
printf( "Enter a number to convert: " );
unsigned int x = 0;
scanf( "%u", &x );
size_t n = 0;
do
{
ptr = realloc( ptr, ( n + 1 ) * sizeof( unsigned int ) );
ptr[n++] = x % Base;
} while ( x /= Base );
while ( n-- )
{
printf( "%u", ptr[n] );
}
putchar( 'n' );
free( ptr );
return 0;
}
一般来说,这样的电话
ptr = realloc( ptr, ( n + 1 ) * sizeof( unsigned int ) );
不安全,因为函数可以返回 NULL。所以一般来说,你应该使用一个中间变量,比如
unsigned int *tmp = realloc( ptr, ( n + 1 ) * sizeof( unsigned int ) );
if ( tmp ) ptr = tmp;