TransWikia.com

Programa usando malloc duas vezes

Stack Overflow em Português Asked by Gabriel Vinicius on January 16, 2021

Por que esse programa que faz a divisão de um número em notação decimal, transforma-o em notação binária e imprime na tela o número na sequencia correto (do bit mais significativo para o menos significativo) usa malloc duas vezes?

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[]) {
    // Stack
    int decimal, q, r;
    int counter, i;
    char *binary = NULL;
    char *aux;

    printf("Digite um número em base decimal: ");
    scanf("%d", &decimal);

    counter = 1;
    while (decimal >= 2) {
        q = decimal / 2;
        r = decimal - (q * 2);

        // Heap
        aux = (char *) malloc(counter * sizeof(char));
        if (binary != NULL) {
            memcpy(aux, binary, counter-1);
            free(binary);
        }
        binary = aux;

        if (r == 0) {
            binary[counter-1] = 48; //'0';
        } else {
            binary[counter-1] = 49; //'1';
        }

        //printf("resto %d = %dn", counter, r);
        counter++;
        decimal = q;
    }
    //printf("ultimo quociente = %dn", q);

    // Heap
    aux = (char *) malloc(counter * sizeof(char));
    if (binary != NULL) {
        memcpy(aux, binary, counter-1);
        free(binary);
    }
    binary = aux;

    if (decimal == 0) {
        binary[counter-1] = 48; //'0';
    } else {
        binary[counter-1] = 49; //'1';
    }

    printf("Resultado em binário = ");
    for (i = counter-1; i >= 0; i--) {
        printf("%c", binary[i]);
    }
    printf("n");

    free(binary);

    return 0;
}

3 Answers

Este exercício que te puseram é interessante: entender o código alheio e eventualmente modificá-lo. O código do enunciado tem a virtude de: introduzir vários conceitos (tipos de memória, mallocs, memcpy, etc,) e ter ainda coisas "melhoráveis"

Em complemento à tua pergunta, se fosse eu (mantendo o espírito do mesmo) para além dos melhoramentos referidos anteriormente,

(1) acabava com a memória dinâmica

   char binary[32];

ou pelo menos alocava tudo de uma vez (tamanho necessário=1+log2(decimal):

   binary=malloc((int)(1+log2(decimal)))

(2) substituía os

   if (r == 0) {
        binary[counter-1] = 48; //'0';
    } else {
        binary[counter-1] = 49; //'1';
    }

por

    binary[counter-1] = r + '0';

em resumo...

...
#include <math.h>

int main() {
    int decimal, q, r, counter;
    char *binary;

    printf("Digite um número em base decimal: ");
    scanf("%d", &decimal);
    binary=malloc((int)(1+log2(decimal)));

    counter = 0;               //from @pmg
    while (decimal > 0) {      //from @Maniero
        q = decimal / 2;
        r = decimal % 2;
        binary[counter] = r + '0';
        counter++;
        decimal = q;
    }

    printf("Resultado em binário = ");
    while (counter--) { putchar(binary[counter]); }
    printf("n");

    free(binary);
    return 0;
}

Answered by JJoao on January 16, 2021

por que esse programa [...] usa malloc duas vezes?

Para números com N bits, o ciclo while do programa corre N - 1 vez. Este ciclo não é executado quando decimal for 0 ou 1.

while (decimal >= 2) { /* ... */ }

Portanto, dentro do ciclo, a alocação feita não é suficiente para guardar a representação binária completa.

Por isso, no fim do ciclo, o programa faz mais uma alocação para o último bit.

Answered by pmg on January 16, 2021

Se o problema é evitar fazer todo cálculo de um dos restos de novo depois que termina o laço, é fácil resolver. O problema é que está parando quando chega no resto 2 e correto é fazer até o resto ser 1. Então uma simples mudança na condição do while resolve isto.

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int main() {
    int decimal;
    printf("Digite um número em base decimal: ");
    scanf("%d", &decimal);
    int counter = 1;
    char *binary = NULL;
    while (decimal >= 1) {
        int q = decimal / 2;
        int r = decimal - (q * 2);
        char *aux = malloc(counter);
        if (binary != NULL) {
            memcpy(aux, binary, counter - 1);
            free(binary);
        }
        binary = aux;
        if (r == 0) binary[counter-1] = '0';
        else binary[counter-1] = '1';
        counter++;
        decimal = q;
    }
    printf("Resultado em binário = ");
    for (int i = counter - 1; i >= 0; i--) printf("%c", binary[i]);
    printf("n");
    free(binary);
}

Veja funcionando no ideone. E no repl.it. Também coloquei no GitHub para referência futura.

Não analisei outros aspectos.

Answered by Maniero on January 16, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP