INE5408 Estruturas de Dados

Slides:



Advertisements
Apresentações semelhantes
Alocação Dinâmida de Memória
Advertisements

Slides Prof. Jean SIMÃO Revisão: Prof. João FABRO
Fundamentos de Programação 1
Estrutura de dados II Carlos Oberdan Rolim Ciência da Computação Sistemas de Informação.
Estruturas de Dados Aula 6: Cadeias de Caracteres
Estruturas de Dados Aulas 3 e 4: Uso da memória e Vetores
Transparência 1 Estruturas de Dados - T.332 Capítulo 3 Parte 2: Alocação Dinâmica de Memória.
INE - UFSC - Disciplina Estruturas de Dados - Prof. Dr. Aldo von Wangenheim Página 1 Estruturas de Dados - T.332 Capítulo 3 Parte 2: Alocação Dinâmica.
Ponteiros em C Prof. Kariston Pereira
Algoritmo e Estrutura de Dados I Aulas 15 – Linguagem C Alocação Dinâmica de Memória Márcia Marra
FUNÇÕES Dilvan Moreira (baseado em material de Z. Liang)
INE5408 Estruturas de Dados Ponteiros, passagem de parâmetros e modelos de memória.
INE5408 Estruturas de Dados Alocação Dinâmica de Memória.
Princípios de Desenvolvimento de Algoritmos MAC122 Prof. Dr. Paulo Miranda IME-USP Alocação Dinâmica de Memória.
Estrutura de Dados (DPADF 0056) Aula 7 – Encadeamento de Memória Universidade Federal de Santa Maria Colégio Agrícola de Frederico Westphalen Curso Superior.
Estrutura de Dados (DPADF 0056) Aula 8 – Estr. Clássicas - Lista Universidade Federal de Santa Maria Colégio Agrícola de Frederico Westphalen Curso Superior.
INE5408 Estruturas de Dados
Estruturas de Dados Aula 2: Estruturas Estáticas
CES-11 ALGORITMOS E ESTRUTURAS DE DADOS Aulas Práticas – 2017
Vetores e Matrizes em C/C++
INF1007: Programação 2 3 – Cadeias de Caracteres
Fundamentos de Programação 1
ESTRUTURA DE DADOS Professor: Marcelo Mendes Turma: MBI-1
INF1007: Programação 2 2 – Alocação Dinâmica
INE5408 Estruturas de Dados
INE5408 Estruturas de Dados
Capítulo II – Listas Lineares Gerais
Fundamentos de Programação 1
Estrutura de Dados Revisão
CES-11 ALGORITMOS E ESTRUTURAS DE DADOS Aulas Práticas
INF1007 – Programação 2 9 – Pilhas
INF1007: Programação 2 9 – Tipos Abstratos de Dados
CES-11 ALGORITMOS E ESTRUTURAS DE DADOS Aulas Práticas
Estruturas de Dados Aula 5: Matrizes
FUNDAMENTO DE PROGRAMAÇÃO PROF. WELLINGTON FRANCO
Fundamentos de Programação 1
FUNDAMENTO DE PROGRAMAÇÃO
FUNDAMENTO DE PROGRAMAÇÃO
Capítulo IV – Árvores Gerais
CES-11 ALGORITMOS E ESTRUTURAS DE DADOS Aulas Práticas
Programação de Computadores I – Arquivos
FUNDAMENTO DE PROGRAMAÇÃO PROF. WELLINGTON FRANCO
Algoritmos e Estruturas de Dados I
UNIDADE 7 Tipos estruturados
INE 5201 – INTRODUÇÃO À CIÊNCIA DA COMPUTAÇÃO
Algoritmos e Programação MC102
Programação de Computadores I – Ponteiros
CES-11 ALGORITMOS E ESTRUTURAS DE DADOS Aulas Práticas
Listas Encadeadas.
Aula 22 Modularização 22/10/08.
CES-11 ALGORITMOS E ESTRUTURAS DE DADOS Aulas Práticas – 2017
Fundamentos de Programação 1
Relembrando... Variáveis : endereçam uma posição de memória que contem um determinado valor dependendo do seu tipo (char, int, float, double, ...) void.
Tipos Abstratos de Dados
Programação de Computadores I – Arquivos
Instalação e Manutenção de Computadores Técnico em Informática MAI1
Orientação a Objetos - Programação em C++
Programação de Computadores I – Ponteiros
DHD – Desenvolvimento em Hardware
Prof. Rafael Mesquita Fila Prof. Rafael Mesquita
Computação Eletrônica Vetores e Matrizes
Algoritmos e Estruturas de Dados I – Ponteiros
Estruturas de Dados em C
Arrays de caracteres: strings
Linguagem C Linguagem Imperativa
DHD – Desenvolvimento em Hardware
DHD – Desenvolvimento em Hardware
Estruturas de Dados Aula 5: Matrizes 16/03/2015. Matrizes Conjuntos bidimensionais declarados estaticamente float mat[4][3]; acesso de elemento: mat[2][0]
Fundamentos de Programação 1
CES-11 ALGORITMOS E ESTRUTURAS DE DADOS Aulas Práticas – 2019
Transcrição da apresentação:

INE5408 Estruturas de Dados Alocação Dinâmica de Memória

As Funções de Alocação Dinâmica de Memória em "C" Alocação Dinâmica é um meio pelo qual o programa pode obter memória enquanto está em execução. Já visto até agora: Constantes são "codificadas" dentro do código objeto de um programa em tempo de compilação. Variáveis globais (estáticas) têm a sua alocação codificada em tempo de compilação e são alocadas logo que um programa inicia a execução. Variáveis locais em funções (ou métodos) são alocadas através da requisição de espaço na pilha (stack).

StackPointer Início da Pilha HeapPointer Início da Área Alocável Topo da Memória #include <stdio.h> char *a, *b; int func_A () { int local1, local2; … } void func_B () { int localA, localB; localA = func_A(); localB = func_A(); main () { a = "Essa aula é legal"; b = "Será mesmo?" func_B(); HeapPointer Início da Área Alocável a b Variáveis estáticas 10010101... P r o g r a m a Código objeto "Essa aula é ... "Será mesmo.. Constantes Sistema Operacional Base da Memória

StackPointer Início da Pilha HeapPointer Início da Área Alocável Topo da Memória #include <stdio.h> char *a, *b; int func_A () { int local1, local2; … } void func_B () { int localA, localB; localA = func_A(); localB = func_A(); main () { a = "Essa aula é legal"; b = "Será mesmo?" func_B(); HeapPointer Início da Área Alocável a b Variáveis estáticas 10010101... Código objeto "Essa aula é ... "Será mesmo.. Constantes Sistema Operacional Base da Memória

StackPointer Início da Pilha HeapPointer Início da Área Alocável Topo da Memória #include <stdio.h> char *a, *b; int func_A () { int local1, local2; … } void func_B () { int localA, localB; localA = func_A(); localB = func_A(); main () { a = "Essa aula é legal"; b = "Será mesmo?" func_B(); HeapPointer Início da Área Alocável a b Variáveis estáticas 10010101... Código objeto "Essa aula é ... "Será mesmo.. Constantes Sistema Operacional Base da Memória

StackPointer Início da Pilha HeapPointer Início da Área Alocável Topo da Memória &main-#3 localA localB #include <stdio.h> char *a, *b; int func_A () { int local1, local2; … } void func_B () { int localA, localB; localA = func_A(); localB = func_A(); main () { a = "Essa aula é legal"; b = "Será mesmo?" func_B(); StackPointer Início da Pilha HeapPointer Início da Área Alocável a b Variáveis estáticas 10010101... Código objeto "Essa aula é ... "Será mesmo.. Constantes Sistema Operacional Base da Memória

StackPointer Início da Pilha HeapPointer Início da Área Alocável Topo da Memória &main-#3 localA localB #include <stdio.h> char *a, *b; int func_A () { int local1, local2; … } void func_B () { int localA, localB; localA = func_A(); localB = func_A(); main () { a = "Essa aula é legal"; b = "Será mesmo?" func_B(); StackPointer Início da Pilha HeapPointer Início da Área Alocável a b Variáveis estáticas 10010101... Código objeto "Essa aula é ... "Será mesmo.. Constantes Sistema Operacional Base da Memória

StackPointer Início da Pilha HeapPointer Início da Área Alocável Topo da Memória &main-#3 localA localB #include <stdio.h> char *a, *b; int func_A () { int local1, local2; … } void func_B () { int localA, localB; localA = func_A(); localB = func_A(); main () { a = "Essa aula é legal"; b = "Será mesmo?" func_B(); &func_B-#2 local1 local2 StackPointer Início da Pilha HeapPointer Início da Área Alocável a b Variáveis estáticas 10010101... Código objeto "Essa aula é ... "Será mesmo.. Constantes Sistema Operacional Base da Memória

StackPointer Início da Pilha HeapPointer Início da Área Alocável Topo da Memória &main-#3 localA localB #include <stdio.h> char *a, *b; int func_A () { int local1, local2; … } void func_B () { int localA, localB; localA = func_A(); localB = func_A(); main () { a = "Essa aula é legal"; b = "Será mesmo?" func_B(); &func_B-#2 local1 local2 StackPointer Início da Pilha HeapPointer Início da Área Alocável a b Variáveis estáticas 10010101... Código objeto "Essa aula é ... "Será mesmo.. Constantes Sistema Operacional Base da Memória

StackPointer Início da Pilha HeapPointer Início da Área Alocável Topo da Memória &main-#3 localA localB #include <stdio.h> char *a, *b; int func_A () { int local1, local2; … } void func_B () { int localA, localB; localA = func_A(); localB = func_A(); main () { a = "Essa aula é legal"; b = "Será mesmo?" func_B(); StackPointer Início da Pilha HeapPointer Início da Área Alocável a b Variáveis estáticas 10010101... Código objeto "Essa aula é ... "Será mesmo.. Constantes Sistema Operacional Base da Memória

StackPointer Início da Pilha HeapPointer Início da Área Alocável Topo da Memória &main-#3 localA localB #include <stdio.h> char *a, *b; int func_A () { int local1, local2; … } void func_B () { int localA, localB; localA = func_A(); localB = func_A(); main () { a = "Essa aula é legal"; b = "Será mesmo?" func_B(); &func_B-#3 local1 local2 StackPointer Início da Pilha HeapPointer Início da Área Alocável a b Variáveis estáticas 10010101... Código objeto "Essa aula é ... "Será mesmo.. Constantes Sistema Operacional Base da Memória

StackPointer Início da Pilha HeapPointer Início da Área Alocável Topo da Memória &main-#3 localA localB #include <stdio.h> char *a, *b; int func_A () { int local1, local2; … } void func_B () { int localA, localB; localA = func_A(); localB = func_A(); main () { a = "Essa aula é legal"; b = "Será mesmo?" func_B(); &func_B-#3 local1 local2 StackPointer Início da Pilha HeapPointer Início da Área Alocável a b Variáveis estáticas 10010101... Código objeto "Essa aula é ... "Será mesmo.. Constantes Sistema Operacional Base da Memória

StackPointer Início da Pilha HeapPointer Início da Área Alocável Topo da Memória &main-#3 localA localB #include <stdio.h> char *a, *b; int func_A () { int local1, local2; … } void func_B () { int localA, localB; localA = func_A(); localB = func_A(); main () { a = "Essa aula é legal"; b = "Será mesmo?" func_B(); StackPointer Início da Pilha HeapPointer Início da Área Alocável a b Variáveis estáticas 10010101... Código objeto "Essa aula é ... "Será mesmo.. Constantes Sistema Operacional Base da Memória

StackPointer Início da Pilha HeapPointer Início da Área Alocável Topo da Memória #include <stdio.h> char *a, *b; int func_A () { int local1, local2; … } void func_B () { int localA, localB; localA = func_A(); localB = func_A(); main () { a = "Essa aula é legal"; b = "Será mesmo?" func_B(); HeapPointer Início da Área Alocável a b Variáveis estáticas 10010101... Código objeto "Essa aula é ... "Será mesmo.. Constantes Sistema Operacional Base da Memória

Alocação Dinâmica em "C" A memória alocada pelas funções de alocação dinâmica é obtida do heap. O heap é a região de memória livre que se encontra entre o programa (com a área de armazenamento permanente) e a pilha (stack). O tamanho do heap é, a princípio, desconhecido do programa. "C" possui duas funções básicas para gerência de memória: malloc(nº de bytes) - aloca memória. free(endereço) - libera memória.

Função malloc() Protótipo: void *malloc(size_t número_de_bytes); Detalhes: devolve um ponteiro do tipo void (sem tipo) para o início (1º byte) da área de memória alocada; isto significa que o valor deste ponteiro pode ser atribuído a qualquer variável do tipo ponteiro. Para isto deve ser utilizado sempre um typecasting. Ex.: se x é um ponteiro para inteiro, então: x = (int *) malloc( sizeof(int) ); número_de_bytes é a quantidade de bytes alocada; se a memória for alocada no topo do heap, o heapPointer é atualizado (incrementado de número_de_bytes); o tipo size_t é definido em stdlib.h.

StackPointer Topo da Pilha HeapPointer Topo da Área Alocável Topo da Memória #include <stdlib.h> #include <stdio.h> char *p; int *q; main() { // Aloca 1000 bytes de RAM. p = (char *) malloc(1000); // Aloca espaço para 50 // inteiros. q = (int *) malloc(50*sizeof(int)); } HeapPointer Topo da Área Alocável 50*int = 200 bytes 1000 bytes p q Variáveis estáticas 10010101... Código objeto Constantes Sist.Operacional Base da Memória

StackPointer Topo da Pilha HeapPointer Topo da Área Alocável Topo da Memória Espaço de variáveis locais alocado malloc devolve: um ponteiro para a área alocada; o ponteiro nulo (NULL) caso não seja possível alocar a memória requisitada. Convém verificar se foi possível alocar a memória. #include <stdio.h> #include <stdlib.h> char *p; main() { ................ // Tenta alocar 1000 bytes de // RAM. p = malloc(1000); // Testa se p é igual a // NULL. if (p == NULL) printf(“%s”, "Sem memória!"); } StackPointer Topo da Pilha HeapPointer Topo da Área Alocável Já alocado antes p Variáveis estáticas 10010101... Código objeto "Sem memória" Constantes Sist.Operacional Base da Memória

Função free() Protótipo: void free( void *p ); Detalhes: devolve memória previamente alocada ao sistema; a memória devolvida é aquela que foi alocada com um ponteiro com o valor de p: o valor de p deve ser um valor que foi alguma vez retornado por malloc(); não é possível alocar um vetor enorme e depois desalocar a parte dele que "sobrou“; a utilização de free() com um valor de ponteiro qualquer poder ter resultados catastróficos; a gerência de buracos no heap é responsabilidade do sistema operacional.

Exercício: Lista com um vetor de Ponteiros para Strings Uma lista ordenada pode conter Strings de qualquer comprimento < 10000; esta lista tem um número de elementos máximo fixo (100) e é implementada como um vetor de ponteiros para Strings; utilize as rotinas de lista com vetor que você implementou para a agenda. Um novo String é lido primeiramente para dentro de uma variável auxiliar qualquer; então é alocada memória para exatamente o seu tamanho e ele é copiado para esta área. Para copiar um String utilize strcpy(); por fim um lugar na lista é encontrado para ele. A posição escolhida do vetor de ponteiros da lista é instanciada através da atualização dos valores do ponteiro da posição do String na lista com o endereço do string.

Modelagem da estrutura Strings lidos do usuário e alocados no Heap 1 S a b ã o \0 C o n s t i t u i r \0 Lista com Vetor de Ponteiros

Modelagem da Lista Pseudo-código: constantes MAXLISTA = 100; tipo tLista { // Vetor de ponteiros para caracter. caracter *dados[MAXLISTA]; inteiro último; }; Importante: observe que criando uma variável do tipo tLista você não vai estar alocando memória para os strings a serem lidos, apenas para os ponteiros para eles.

Organização de memória para o exercício Topo da Memória StackPointer Topo da Pilha Espaço de variáveis locais alocado Organização de memória para o exercício HeapPointer Topo da Área Alocável str4 str3 str2 str1 Var.Estáticas Vetor de char* 10010101... Código objeto Constantes Sist.Operacional Base da Memória

Para verificar o comprimento de um String: utilize a função strlen(); esta função devolve o comprimento (em caracteres imprimíveis) de um string. Protótipo: int strlen(char *p); #include <stdio.h> #include <stdlib.h> #include <sting.h> char p[90] = "Carro"; main() { printf("%i", strlen(p)); } Imprime: 5

Para copiar um String: Imprime: Carro utilize a função strcpy(); esta função copia o conteúdo de um string (dado por um apontador) para a posição de memória dada por outro apontador. Protótipo: char *strcpy(char *destino, char *fonte); #include <stdio.h> #include <stdlib.h> #include <sting.h> char p[90] = "Carro"; char lata[20]; main() { strcpy(lata, p)); printf("s%", lata); } Imprime: Carro

Detalhes: Lista Ordenada com um vetor de ponteiros para Strings Como você não sabe o comprimento do String que o usuário vai digitar, use primeiro uma variável auxiliar grande (10000 posições) para guardar o que foi digitado; a lista deve ser passada como parâmetro para todas as funções que a utilizam, bem como as variáveis de controle da lista; todas as funções de lista ordenada implementadas anteriormente devem ser reimplementadas para utilizar estes Strings; para a leitura de um String utilize scanf("%s", entrada).

Exercício 2: Trabalho com Passagem de Parâmetros Agora você vai fazer um programa que manipula mais de uma lista; o programa fará isto com um único conjunto de funções e passagem das diversas listas como parâmetros; como aplicação imaginemos um sistema de contabilidade simples; você vai ter um Plano de Contas constituído por duas listas: débitos e créditos; o mesmo conjunto de funções (que você já implementou) vai poder ser utilizado para isso: você somente precisa ampliar o conjunto de parâmetros da função para passar por referência também a lista que você quer alterar. A passagem de parâmetro da lista deve ser por referência porque você deseja que as alterações sejam persistentes.

Modelagem de um Lançamento Cada lista de débitos ou créditos é constituída por lançamentos. Cada lançamento possui: um valor real (positivo); um nome. Por exemplo, “Pagar proteção à Mafia” Estrutura: tipo tLançamento { caracter *nome; real valor; };

Modelagem de um tipo Lista para Débitos ou Créditos Pseudo-código: constantes MAXLISTA = 100; tipo tListaContábil { tLançamento dados[MAXLISTA]; inteiro último; }; Importante: observe que criando um vetor de lançamentos, você não vai estar reservando memória para os nomes destes, pois o campo nome é só um ponteiro.

Usando (pseudo-código) Crie variáveis globais: tListaContábil débitos, créditos; Passe estas variáveis como parâmetros por referência: adiciona(&débitos, nomeLanc, valorLanc); Cabeçalho: Inteiro FUNÇÃO adiciona(tListaContábil *plano; caracter *nome; real valor); Importante: nome é passado como ponteiro para caracter. Use um buffer global para ler o nome do lançamento do usuário.

Modelagem da estrutura Strings lidos do usuário e alocados no Heap 1 R$ 5,00 S a b ã o \0 R$ 505,00 P a s s a g e n s \0 Lista de débitos ou de créditos com Vetor de Estruturas do tipo Lançamento

Usando (código “C”) Referencie diferentemente se estiver usando ponteiros para a lista ou a lista diretamente: tListaContabil debitos, creditos; debitos.dados[2].valor = 5.0; strcpy(debitos.dados[2].nome, buffer); Dentro das funções: Suponha: tListaContabil *ponteiro e ponteiro = &debitos; ponteiro->dados[2].valor = 5.0; strcpy(ponteiro->dados[2].nome, buffer);

Headerfile: como garantir Inclusão Única // Arquivo: pilha.h #ifndef EstruturaDaPilha #define EstruturaDaPilha // Definir uma estrutura para a pilha. struct estruturaDaPilha { int topo; int dados[MAXPILHA]; }; // Define um tipo que tem a estrutura da // pilha. typedef struct estruturaDaPilha pilha; #endif

Headerfiles: Importante A diretiva de compilação #ifndef (if not defined) diz que aquela área de código fonte entre o #ifndef e o #endif somente será levada em conta pelo compilador se o argumento de #ifndef ainda não houver sido definido na mesma sessão de compilação no escopo de um módulo; isso garante que código que a gente "por via das dúvidas" inclui mais de uma vez em um módulo não seja considerado duas vezes; um exemplo de como isto é útil está na diretiva #include <stdio.h> que está presente tanto em pilha.h quanto em pilha.c e em aplic.c; como aplic.c carrega pilha.h "para dentro" de si mesmo, carregará também stdio.h. Como está explicitamente também carregando stdio.h, se não houver uma diretiva #ifndef em stdio.h, ele terá o mesmo código existente em stdio.h duas vezes.

Módulo: lista.h #ifndef Lista #define Lista typedef struct estruLista { char *elemento[30]; int ultimo; int max; }; typedef struct estruLista lista; #endif

Módulo: lista.c #include <stdio.h> #include <stdlib.h> #include “lista.h” lista *criaLista() { lista *nova; nova = malloc( sizeof(lista) ); nova->max = 30; nova->ultimo = -1; return (nova); } void destroiLista(lista *morta) { int i; // Libera memória ocupada pelos Strings. for (i=0; morta->ultimo; i++) free( morta->elemento[i] ); // Libera memória da lista. free( morta );

Exercício de Implementação 4 Implementação de um programa com número variável de filas com vetores alocadas dinamicamente usando o TAD lista com vetor. Este trabalho é bem fácil porque você já implementou praticamente tudo o que precisa. Só tem agora que modificar um pouco a forma de gerenciar os seus dados. Tome o TAD Fila com Vetor que você já implementou e crie um programa para gerenciar uma lista contendo um número variável e menor do que 20 desses TADs. Cada Fila deverá ter no máximo 20 posições. Para tanto adapte o TAD Lista com Vetor que você implementou de forma que cada elemento da lista seja um tipo ponteiro para um TAD Fila. Quando você for inserir uma nova fila, você a cria dinamicamente, alocando memória para ela e inicializando os seus campos de controle.