Desafio C

Vetor dinâmico sem vazamentos

Enunciado

Implemente um programa que leia uma sequência de números inteiros positivos do usuário (terminada por 0) e armazene-os em um vetor dinâmico que cresce conforme a necessidade. A cada leitura, se o vetor estiver cheio, dobre sua capacidade usando realloc. Ao final, exiba todos os números na ordem em que foram digitados e libere toda a memória. Certifique-se de que não haja vazamentos.

Requisitos

  • Usar malloc para a alocação inicial.
  • Usar realloc para dobrar a capacidade quando necessário.
  • Ler números até que 0 seja digitado (0 não deve ser armazenado).
  • Exibir os números na ordem de entrada.
  • Liberar a memória com free.
  • Verificar erros de alocação.

Código inicial

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

int main(void) {
    int capacidade = 4;
    int tamanho = 0;
    int *vetor = malloc(capacidade * sizeof(int));
    if (vetor == NULL) {
        printf("Erro: malloc falhou\n");
        return 1;
    }

    int num;
    printf("Digite números (0 para sair): ");
    while (scanf("%d", &num) == 1 && num != 0) {
        // Seu código aqui
    }

    // Exibir e liberar
    return 0;
}

Saída esperada

Digite números (0 para sair): 10 20 30 40 50 0
10 20 30 40 50
Ver dica

Quando tamanho == capacidade, use realloc para dobrar a capacidade. Lembre-se de atualizar o ponteiro corretamente e verificar falhas.

Mostrar solução
#include <stdio.h>
#include <stdlib.h>

int main(void) {
    int capacidade = 4;
    int tamanho = 0;
    int *vetor = malloc(capacidade * sizeof(int));
    if (vetor == NULL) {
        printf("Erro: malloc falhou\n");
        return 1;
    }

    int num;
    printf("Digite números (0 para sair): ");
    while (scanf("%d", &num) == 1 && num != 0) {
        // Se o vetor estiver cheio, dobra a capacidade
        if (tamanho == capacidade) {
            capacidade *= 2;
            int *novo_vetor = realloc(vetor, capacidade * sizeof(int));
            if (novo_vetor == NULL) {
                printf("Erro: realloc falhou\n");
                free(vetor);
                return 1;
            }
            vetor = novo_vetor;
        }
        vetor[tamanho++] = num;
    }

    // Exibe os números armazenados
    for (int i = 0; i < tamanho; i++) {
        printf("%d ", vetor[i]);
    }
    printf("\n");

    // Libera a memória
    free(vetor);
    return 0;
}

Passo a passo

  1. Inicializamos capacidade = 4 e tamanho = 0. Alocamos espaço para 4 inteiros com malloc.
  2. Verificamos se malloc retornou NULL.
  3. Iniciamos um laço que lê números com scanf até que o valor seja 0 ou a leitura falhe.
  4. Dentro do laço, se tamanho == capacidade, dobramos capacidade e chamamos realloc para expandir o bloco. Usamos um ponteiro temporário novo_vetor para não perder vetor em caso de falha.
  5. Se realloc falhar, liberamos vetor e encerramos. Caso contrário, atualizamos vetor = novo_vetor.
  6. Armazenamos o número lido em vetor[tamanho] e incrementamos tamanho.
  7. Após o laço, exibimos todos os elementos armazenados.
  8. Liberamos a memória com free(vetor).

Por que funciona

O vetor cresce dinamicamente conforme a necessidade, evitando desperdício e permitindo armazenar uma quantidade arbitrária de números. O uso de realloc com verificação de erro garante que a memória seja gerenciada corretamente. A liberação final evita vazamentos.

Erros comuns

  • Não verificar o retorno de realloc: se falhar, o ponteiro original é perdido, causando vazamento.
    vetor = realloc(vetor, capacidade * sizeof(int)); // perigoso
    
    Corrija usando um ponteiro temporário.
  • Esquecer de dobrar a capacidade antes de realocar: isso pode causar realocação desnecessária ou estouro.
  • Não liberar a memória no final: o programa termina, mas o vazamento é uma má prática.
  • Acessar vetor após free: certifique-se de não usar o ponteiro depois de liberar.

Outra forma de resolver

Poderia usar uma lista encadeada, que não requer realocação, mas tem maior overhead de memória e pior localidade de cache. O vetor dinâmico é mais eficiente para acesso aleatório.

Saída esperada

Digite números (0 para sair): 10 20 30 40 50 0
10 20 30 40 50