Baixe o app para aproveitar ainda mais
Prévia do material em texto
NOTAS DE AULA – ALGORITMOS E PROGRAMAÇÃO DE COMPUTADORES 55 Prof. Rodrigo de Oliveira Alocação Dinâmica de Memória • Quando um programa é executado, ele é copiado da memória secundária (disco rígido, disquete, CD, etc.) para a memória RAM do computador. A memória ocupada pelo programa inclui tanto o código do programa quanto o espaço necessário para os seus dados estáticos (variáveis e constantes declaradas). O que sobra da memória RAM é o que está disponível para a alocação dinâmica. No entanto, não se sabe exatamente quanto de memória pode ser alocada dinamicamente, sendo necessário checar o retorno das funções de alocação dinâmica para averiguar se houve alguma falha. • Usado quando não se sabe exatamente a quantidade necessária de memória a ser alocada pelo programa. • Para usar as funções de alocação dinâmica de memória, deve-se incluir a biblioteca stdlib.h. o Em alguns compiladores, é necessário incluir também a biblioteca malloc.h. • Importante: Toda a memória alocada dinamicamente deve ser liberada usando a função free(). Funções principais para alocação de memória malloc() • void *malloc(size_t num); • Aloca num bytes de espaço para armazenamento e retorna um ponteiro para o primeiro byte. • Retorna NULL se não foi possível alocar o espaço requisitado ou se num = 0. • size_t é normalmente um sinônimo para unsigned na maioria dos compiladores. calloc() • Ao invés de alocar um grupo de bytes (como a função malloc), aloca um grupo de objetos. • void *calloc(size_t num, size_t tamanho); • Aloca num objetos de tamanho bytes e retorna um ponteiro para o primeiro byte. • Retorna NULL se não foi possível alocar o espaço requisitado ou se num = 0. realloc() • Muda o tamanho do bloco de memória alocado previamente pela função malloc() ou calloc(). • void *realloc(void *ptr, size_t novo_tamanho); • Realoca novo_tamanho bytes de espaço na memória RAM para o ponteiro ptr. o Se existe espaço na memória para expansão do bloco, aloca o restante e retorna o ponteiro ptr. o Se não existe espaço na memória para expansão do bloco, desaloca o bloco e aloca um novo bloco com o novo tamanho, retornando um novo ponteiro ptr para esta nova posição da memória. o Se ptr = NULL, a função funciona como o malloc(). o Se novo_tamanho = 0, a memória alocada por ptr é liberada e realloc() retorna NULL. o Se não existe espaço na memória nem para expansão do bloco e nem para realocação em outra posição, realloc() retorna NULL e o bloco original não é alterado. int *ptr_vet; ptr_vet = (int*) malloc(50 * sizeof(int)); /* aloca vetor de 50 inteiros */ free(ptr_vet); int *ptr_vet; ptr_vet = (int*) calloc(50, sizeof(int)); /* aloca vetor de 50 inteiros */ free(ptr_vet); NOTAS DE AULA – ALGORITMOS E PROGRAMAÇÃO DE COMPUTADORES 56 Prof. Rodrigo de Oliveira Exercícios: a) Vetor positivo dinâmico – Escreva um programa que implementa um vetor dinâmico, onde o usuário começa a digitar números inteiros positivos e estes são guardados no vetor. A cada momento, o vetor deve possuir tamanho igual ao número de valores digitados pelo usuário. Quando o usuário digitar um número negativo, significa que acabou a lista de números e o programa deve imprimir todos eles no monitor. #include <stdio.h> #include <stdlib.h> int main() { int *ptr_vet, *ptr_vet_teste, tamanho, temp, passo; int mem_suf = 1; tamanho = 0; scanf("%d", &temp); while ((temp >= 0) && mem_suf) { tamanho++; if (tamanho == 1) { ptr_vet = (int*) malloc(sizeof(int)); if (ptr_vet == NULL) { printf("Memória insuficiente"); mem_suf = 0; } else *ptr_vet = temp; } else { // "ptr_vet_teste" usado para não perder o ponteiro caso não exista espaço ptr_vet_teste = (int*) realloc(ptr_vet, (tamanho * sizeof(int))); if (ptr_vet_teste == NULL ) { printf("Memória insuficiente"); mem_suf = 0; tamanho--; } else { ptr_vet = ptr_vet_teste; *(ptr_vet + (tamanho - 1)) = temp; } } scanf("%d", &temp); } if (tamanho > 0) { for (passo = 0; passo < tamanho; passo++) printf("%d ", *(ptr_vet + passo)); } else printf("Nenhum valor positivo digitado."); free(ptr_vet); return 0; } int *ptr_vet; ptr_vet = (int*) malloc(50 * sizeof(int)); /* aloca vetor de 50 inteiros */ ptr_vet = (int*) realloc(ptr_vet, (60 * sizeof(int))); /* realoca p/ 60 inteiros */ free(ptr_vet); NOTAS DE AULA – ALGORITMOS E PROGRAMAÇÃO DE COMPUTADORES 57 Prof. Rodrigo de Oliveira b) Vetor dinâmico – Reescreva o programa anterior sem a limitação de números negativos, interrompendo a captura dos números quando o usuário digitar um ponto final (“.”). c) Relatório de pedidos de um mini-mercado – Um mini-mercado que possui computadores bem antigos com pouca memória secundária e RAM optou por usar arquivos texto ao invés de um banco de dados para manter seus registros de pedidos de clientes. Neste mercado, apenas as entidades cliente e produto foram consideradas relevantes. Quanto ao cliente, só precisavam saber seu código e nome e, quanto ao produto, seu código, descrição e preço. Para que pudesse ser registrado cada produto comprado por um cliente, surgiu uma nova entidade chamada pedido, na qual armazenava-se seu código, cliente que realizou o pedido, produto comprado e quantidade do mesmo. A esquematização deste cenário usando tabelas é apresentada a seguir: Cada registro das tabelas (por exemplo, um dado cliente na tabela cliente) constitui uma linha no arquivo texto e cada campo de um registro (por exemplo, código e nome do cliente) é separado por uma tabulação. Tem-se a seguir um exemplo de composição dos arquivos cliente.txt, produto.txt e pedido.txt: CLIENTE.TXT 1 Joao Oliveira 2 Maria das Gracas Pereira PRODUTO.TXT 1 Cerveja Skol em lata 350ml 0.93 2 Lasanha Sadia 5.25 3 Coca-cola 2 litros 2.10 4 Pao frances 0.18 5 Danete 1.60 6 Garrafao de vinho Chapinha 18.20 PEDIDO.TXT 1 1 1 12 1 1 6 1 2 2 2 1 2 2 4 4 2 2 5 2 3 1 3 3 Escreva um programa que recebe a localização destes três arquivos e apresenta relatórios de pedidos para este mini-mercado. O programa deve receber um um número correspondente ao código de um pedido e apresentar um relatório deste pedido como a seguir: CLIENTE código do cliente nome do cliente PRODUTO código do produto descrição do produto preço do produto PEDIDO código do pedido código do cliente que efetuou o pedido código do produto comprado no pedido quantidade do produto comprado no pedido NOTAS DE AULA – ALGORITMOS E PROGRAMAÇÃO DE COMPUTADORES 58 Prof. Rodrigo de Oliveira Exemplo para o pedido de código 1: Entrada: cliente.txt produto.txt pedido.txt 1 Saída (quantidade do produto | nome do produto | preço unitário do produto): João Oliveira 12 Cerveja Skol em lata 350ml 0.93 1 Garrafao de vinho Chapinha 18.20 Total 29.36 Exemplo para o pedido de código 2: Entrada: cliente.txt produto.txt pedido.txt 2 Saída (quantidade do produto | nome do produto | preço unitário do produto): Maria das Graças Pereira 1 Lasanha Sadia 5.25 4 Pao frances 0.18 2 Danete 1.60 Total 9.17 Exemplo para o pedido de código 3: Entrada: cliente.txt produto.txt pedido.txt 3 Saída (quantidade do produto | nome do produto | preço unitário do produto): João Oliveira 3 Coca-cola 2 litros 2.10 Total 6.30 Exemplo para o pedido de código 4 (inexistente): Entrada: cliente.txt produto.txt pedido.txt 4 Saída: 0 Dicas úteis:- Ao usar a função fscanf() para buscar os dados nos arquivos texto, a tabulação é encontrada usando “\t” na string de controle. - A conversão de uma cadeia de caracteres em double é feita pela função atof(). Exemplo: double d = atof(“9.22”); // o mesmo que d = 9.22; Observações: - Não armazene as informações dos arquivos em memória RAM para só então fazer a busca pelo pedido. - Use estrutura (struct) para armazenar um registro de relatório de pedidos em memória RAM. - Use alocação dinâmica de memória para armazenar os registros do pedido cujo relatório será gerado.
Compartilhar