简体   繁体   English

程序不使用动态数组输出任何内容

[英]Program doesn't output anything using a dynamic array

I just started with C and I am trying to create a program which takes a number and converts it to binary using this method (from indepth.dev ):我刚开始使用 C,我正在尝试创建一个程序,该程序接受一个数字并使用此方法(来自indepth.dev )将其转换为二进制:

To convert integer to binary, start with the integer in question and divide it by 2 keeping notice of the quotient and the remainder.要将整数转换为二进制,请从所讨论的整数开始,然后将其除以 2,同时注意商和余数。 Continue dividing the quotient by 2 until you get a quotient of zero.继续将商除以 2,直到商为零。 Then just write out the remainders in the reverse order.然后只需按照相反的顺序写出余数。 (...) Now, we simply need to write out the remainder in the reverse order —1100. (...) 现在,我们只需要以相反的顺序写出余数 - 1100。 So, 12 in decimal system is represented as 1100 in binary.因此,十进制中的 12 表示为二进制中的 1100。

I am trying to make the array dynamic in size.我正在尝试使数组的大小动态化。 Coming from Python this is a bit confusing, because in Python you can just append to a list.来自 Python 这有点令人困惑,因为在 Python 中你可以只附加到一个列表。

Here is my code so far:到目前为止,这是我的代码:

#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;
}

When I run the program and enter a number it doesn't output anything.当我运行程序并输入一个数字时,它不会输出任何内容。 If I do the same with a fixed array size it works.如果我用固定的数组大小做同样的事情,它就可以工作。 Why is this happening?为什么会这样?

The problem lies in these few lines:问题在于这几行:

for (i = 0; n>0; i++)
{   
    ptr = realloc(ptr, i * sizeof(int));
    ptr[i] = n % 2;
    n = n/2;
}

You are reallocating an array capable of holding i integers each time, however you end up writing at index i .您每次都在重新分配一个能够容纳i整数的数组,但是您最终在索引i处写入。 An array holding i integers has indexes from 0 to i - 1 , and you are therefore writing past the end of the array.包含i整数的数组的索引从0i - 1 ,因此您写入的内容超过了数组的末尾。 This results in undefined behavior .这会导致未定义的行为

The easiest fix for this is to just start with i = 1 and write to ptr[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;
}

A simpler approach would be to use a fixed size array.一种更简单的方法是使用固定大小的数组。 You already know that an int is 8*sizeof(int) bits long, so that's the maximum you'll need.您已经知道int长度为8*sizeof(int)位,因此这是您需要的最大值。 Also, you probably don't need to work with signed integers since those can cause problems with negative values (therefore you can use unsigned ).此外,您可能不需要使用有符号整数,因为它们可能会导致负值出现问题(因此您可以使用unsigned )。

EDIT: I am saying 8 * sizeof(int) because the sizeof operator returns the size of the type (in this case int ) in bytes.编辑:我说8 * sizeof(int)因为sizeof运算符以字节为单位返回类型的大小(在本例中为int )。 A byte is 8 bits, so I multiply that by 8 to get the size in bits.一个字节是 8 位,因此我将其乘以 8 以获得以位为单位的大小。 I said 8 here, but using CHAR_BIT (from limits.h ) would be better, because a "byte" in C could be expressed using more than 8 bits and in that case CHAR_BIT holds the right number of bits per byte.我在这里说的是8 ,但使用CHAR_BIT (来自limits.h )会更好,因为 C 中的“字节”可以使用超过 8 位来表示,在这种情况下, CHAR_BIT每字节保存正确的位数。 I'm not aware of any C implementation that has a value different than 8 for CHAR_BIT , but it's nonetheless the correct way to go.我不知道任何 C 实现的CHAR_BIT值不同于8 ,但它仍然是正确的方法。 I updated the code below to use CHAR_BIT instead of 8 .我更新了下面的代码以使用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;
}

Bonus:奖金:

#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;
}

You allocated not enough memory.您分配的内存不足。 If sizeof( int ) is equal to 4 then the number of binary digits can be equal to 32 ( sizeof( int ) * CHAR_BIT ).如果sizeof( int )等于4则二进制位数可以等于32 ( sizeof( int ) * CHAR_BIT )。

And there is no need to use realloc.并且不需要使用realloc。

Moreover this statement而且这个说法

ptr = realloc(ptr, i * sizeof(int));

allocates memory of zero size when i in the loop is equal to 0. You may not write to such a memory.当循环中的i等于 0 时,分配零大小的内存。您不能写入这样的内存。

Also you should use an object of the type unsigned int.您还应该使用 unsigned int 类型的对象。

Here is a demonstrative program.这是一个演示程序。

#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;
}

Its output might look like它的输出可能看起来像

Enter a number to convert: 12
1100

If you want to use realloc then the code can look like如果你想使用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;
}

In general such a call一般来说这样的调用

ptr = realloc( ptr, ( n + 1 ) * sizeof( unsigned int ) );

is unsafe because the function can return NULL.是不安全的,因为该函数可以返回 NULL。 So in general you should use an intermediate variable like所以一般来说你应该使用一个中间变量,比如

unsigned int *tmp = realloc( ptr, ( n + 1 ) * sizeof( unsigned int ) );
if ( tmp ) ptr = tmp;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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