Программа ничего не выводит, используя массив Dynami c - PullRequest
0 голосов
/ 15 января 2020

Я только начал с C, и я пытаюсь создать программу, которая берет число и преобразует его в двоичную, используя этот метод (из indepth.dev ):

Чтобы преобразовать целое число в двоичное, начните с рассматриваемого целого числа и разделите его на 2, помня о частном и оставшейся части. Продолжайте делить частное на 2, пока не получите частное, равное нулю. Затем просто запишите остатки в обратном порядке. (...) Теперь нам просто нужно выписать остаток в обратном порядке - 1100. Итак, 12 в десятичной системе представляется как 1100 в двоичном виде.

Я пытаюсь сделать массив динамическим c в размере. Исходя из 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;
}

Когда я запускаю запрограммируйте и введите число, которое ничего не выводит. Если я делаю то же самое с фиксированным размером массива, это работает. Почему это происходит?

Ответы [ 2 ]

1 голос
/ 15 января 2020

Вы выделили недостаточно памяти. Если sizeof( int ) равно 4, то число двоичных цифр может быть равно 32 (sizeof( int ) * CHAR_BIT).

И нет необходимости использовать reallo c.

Более того, этот оператор

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

выделяет память нулевого размера, когда i в l oop равно 0. Вы не можете писать в такую ​​память.

Также вы должны использовать объект типа unsigned 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;
1 голос
/ 15 января 2020

Проблема заключается в следующих нескольких строках:

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 для CHAR_BIT, но, тем не менее, это правильный путь к go. Я обновил код ниже, чтобы использовать 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;
}
...