8-Modulo7

Page 1

Curso Profissional de Informática de Gestão

Módulo 7: Estruturas dinâmicas

LINGUAGENS DE PROGRAMAÇÃO

Conteúdos 1. Introdução Conceitos de estruturas dinâmicas 2. Regras de declaração de estruturas dinâmicas 1.

2. Técnicas de manipulação de informação em

estruturas dinâmicas 3. Noções de pilha e fila de espera 4. Operações básicas sobre listas unidireccionais e bidireccionais

Curso Profissional de Informática de Gestão - 2008/2011 - Módulo 7


Conceitos básicos (Quase) tudo o que acontece num computador, passa-se em

memória – normalmente RAM. É na RAM que são carregados os nossos programas, jogos,

processadores de texto, etc. É também na RAM que são armazenadas as variáveis que fazem parte dos nosso programas. De facto a memória RAM pode ser vista como um enorme

vector de Bytes consecutivos. 100

101

102

5000

5001

5002

Sempre que declaramos uma variável, temos que indicar qual o

seu tipo e qual o seu nome:

char ch; ch

100

101

102

5000

5001

5002

Curso Profissional de Informática de Gestão - 2008/2011 - Módulo 7

Conceitos básicos ch

100

101

102

5000

5001

5002

A variável ch ocupa, o Byte de memória número 5000. Para os programadores, é muito mais simples referenciar uma variável pelo seu nome de que referenciá-la pela posição que essa variável ocupa em memória. Quando se faz ch = ’A’; o que se está a dizer ao computador é “vai à posição 5000 e coloca o caracter ’A’”. É o compilador que realiza esta conversão e não o programador. Este apenas tem que se preocupar em escrever o programa correctamente. Curso Profissional de Informática de Gestão - 2008/2011 - Módulo 7


Conceitos básicos NOTA NOTA: O compilador associa a cada variável uma posição ÚNICA em memória, capaz de suportar dados do tipo dessa variável. Sempre que num programa se faz referência a uma variável, estamos na realidade a referir o endereço ou conjunto de endereços que essa variável ocupa.

Curso Profissional de Informática de Gestão - 2008/2011 - Módulo 7

Apontadores Os apontadores são um mecanismo particularmente flexível

de manipulação de dados, pois permitem manipular directamente dados contidos em endereços específicos de memória. Suponhamos então que tínhamos ao nosso dispor um

apontador denominado ptr. Como qualquer variável ptr ocupa uma posição em memória. ptr

100

ch

101

102

5000

5001

5002

Para colocarmos ptr a apontar para a variável ch, bastará

colocar o endereço de ch em ptr. Isso faz-se utilizando o operador & (Endereço Endereço de). de ptr = &ch; ptr

ch

5000 100

101

102

5000

5001

Curso Profissional de Informática de Gestão - 2008/2011 - Módulo 7

5002


Declaração de apontadores Um apontador é uma variável como qualquer

outra. O seu objectivo é armazenar o endereço de outra variável, que é, por sua vez, um número. A sintaxe da declaração de um apontador é a seguinte: tipo * ptr; Em que: – nome da variável do tipo apontador – tipo da variável à qual apontará – indica que é uma variável do tipo apontador

ptr tipo *

Curso Profissional de Informática de Gestão - 2008/2011 - Módulo 7

Exemplos char a, b, *p, c, *q; int idade, *p_idade;

Curso Profissional de Informática de Gestão - 2008/2011 - Módulo 7


Inicialização de Apontadores A inicialização de apontadores faz-se através

do operador Endereço de – &. Tal operador pode também ser utilizado para inicializar uma variável do tipo apontador no momento da sua declaração. Exemplo: int x = 5; float pi = 3.14; int *ptr_x = &x; float *pointer_to_pi = π Curso Profissional de Informática de Gestão - 2008/2011 - Módulo 7

Um bom hábito para evitar problemas na

programação é efectuar SEMPRE a inicialização dos apontadores. No entanto podem existir situações em que se declara um apontador que não aponta para variável alguma. Nesse caso pode colocar-se a apontar para NULL. A constante simbólica NULL, quando colocada

num apontador, indica que este não aponta para nenhuma variável.

Curso Profissional de Informática de Gestão - 2008/2011 - Módulo 7


Apontadores e vectores O nome de um vector corresponde ao

endereço do seu primeiro elemento, isto é se &v[0] [0]. v for um vector v == &v [o nome de um vector não é mais do que o endereço do primeiro elemento do vector]

Embora o nome de um vector seja um

apontador para o primeiro elemento do vector, este apontador não pode ser alterado durante a execução do programa a que pertence. Se tal fosse possível, havia o risco de perder o vector previamente declarado. Curso Profissional de Informática de Gestão - 2008/2011 - Módulo 7

Apontadores e vectores int v[3] = {10, 20, 30}; int *ptr; Existem duas formas de colocar o apontador ptr a apontar para o primeiro elemento de v ptr = &v[0]; ptr = v; Ao contrário de v, que é um vector, ptr é um apontador puro, pelo que pode ser alterado com endereços diferentes ao longo da execução do programa, não estando obrigado a apontar, eternamente, para o primeiro elemento do vector, como acontece com v. Pode assim apontar para cada um dos elementos do vector v. Curso Profissional de Informática de Gestão - 2008/2011 - Módulo 7


Aritmética de apontadores Incremento / Decremento Um apontador pode ser incrementado como qualquer variável. No entanto o incremento de 1 unidade não significa que o endereço anteriormente armazenado no apontador seja incrementado um Byte. Na realidade, se ptr é um apontador para um determinado tipo, quando ptr é incrementado, por exemplo 1 unidade, o endereço que passa a conter é igual ao endereço anterior de ptr + sizeof(tipo) para que o apontador aponta, isto é, o apontador avança não um Byte mas sim a dimensão do tipo do objecto para o qual aponta. Curso Profissional de Informática de Gestão - 2008/2011 - Módulo 7

Aritmética de apontadores Incremento / Decremento O decremento funciona da mesma forma que

o incremento anteriormente apresentado. Um apontador do tipo xyz recua sempre sizeof(xyz) Bytes por cada unidade de decremento.

Curso Profissional de Informática de Gestão - 2008/2011 - Módulo 7


Diferença A operação de diferença entre dois

apontadores para elementos do mesmo tipo permite saber quantos elementos existem entre um endereço e outro. Por exemplo, o comprimento de uma string pode ser obtido através da diferença entre o endereço do caracter ’\0’ e o endereço do primeiro caracter (ou da string). A diferença entre apontadores só pode ser realizada entre apontadores do mesmo tipo. Curso Profissional de Informática de Gestão - 2008/2011 - Módulo 7

Comparação É também possível a comparação entre dois

apontadores para o mesmo tipo, utilizando os operadores relacionais. A diferença e a comparação entre apontadores só pode ser realizada entre apontadores do mesmo tipo.

Curso Profissional de Informática de Gestão - 2008/2011 - Módulo 7


Quadro-resumo Operação

Exemplo

Observações

Atribuição

ptr = &x

Podemos atribuir um valor (endereço) a um apontador. Se quisermos que aponte para nada podemos atribuir-lhe o valor constante NULL.

Incremento

ptr = ptr+2 Incremento de 2*sizeof(tipo) de ptr.

Decremento

ptr=ptr-10

Decremento de 10*sizeof(tipo) de ptr.

Apontado por *ptr

O operador asterisco permite obter o valor existente na posição cujo endereço está armazenado em ptr.

Endereço de

&ptr

Tal como qualquer outra variável, um apontador ocupa espaço em memória. Desta forma podemos saber qual o endereço que um apontador ocupa em memória.

Diferença

ptr1-ptr2

Permite saber qual o nº de elementos entre ptr1 e ptr2.

Comparação

ptr1>ptr2

Permite verificar, por exemplo, qual a ordem de dois elementos num vector, através do valor dos seus endereços.

Curso Profissional de Informática de Gestão - 2008/2011 - Módulo 7

Apontadores e vectores – Acesso aos elementos Suponhamos a seguinte declaração:

char s[] = ”OlaOleOli”; char *ptr = s; /* ptr fica com o &s[0] */ Como poderemos aceder ao caracter ’a’ presente na string? s[2]

Caracter existente na posição índice 2 do vector

*(ptr+2)

Como ptr contém o endereço do primeiro caracter, se lhe adicionarmos 2, obtemos o endereço do caracter ’a’. Para obter o caracter ’a’ bastará usar o operador * (apontado por).

*(s+2)

Se s == &s[0] pode usar-se a mesma estratégia que foi usada no exemplo anterior.

ptr[2]

O endereçamento de elementos através de parêntesis rectos pode ser realizado também por apontadores, como se de um vector se tratasse. Curso Profissional de Informática de Gestão - 2008/2011 - Módulo 7


Passagem de vectores para funções Sempre que se declara um vector, o seu espaço é alocado contiguamente na memória. A posição que este ocupa em memória pode ser obtida pelo nome do vector que contém o endereço do primeiro elemento. Sempre que é invocada uma função e passado um vector como parâmetro, esta na realidade não recebe o vector na sua totalidade, mas apenas o endereço inicial do vector, pois estamos a passar s == &s[0]. Se passamos um endereço, então a variável que o recebe terá que ser um apontador para o tipo dos elementos do vector. Curso Profissional de Informática de Gestão - 2008/2011 - Módulo 7

Exemplo

Curso Profissional de Informática de Gestão - 2008/2011 - Módulo 7


Passagem de vectores para funções Sempre que se passa um vector para uma

função, apenas o endereço original deste é efectivamente enviado para a função. É assim impossível saber, dentro de uma função, qual a dimensão dos vectores que forma passados, a menos que se envie um outro parâmetro indicador do nº de elementos ou um terminador em cada vector. É da responsabilidade do programador garantir que os vectores enviados para as funções contêm os elementos necessários ao processamento a que irão ser sujeitos. Curso Profissional de Informática de Gestão - 2008/2011 - Módulo 7

Bibliografia Damas, Luís; LINGUAGEM C; FCA; 2ª edição; Lisboa;

1999 Aguilar, Luis Joyanes; FUNDAMENTOS DE PROGRAMAÇÃO – Algoritmos, estruturas de dados e objetos; Mc Graw Hill; Tradução da 3ª edição; São Paulo; 2008 Azul, Artur Augusto; BASES DE PROGRAMAÇÃO 10; Porto Editora; Porto http://www.eisnt.com/GPSI/programacao/Aula4C.pdf http://www.linhadecodigo.com.br/Artigo.aspx?id=425 http://www.criarweb.com/artigos/825.php http://deei.fct.ualg.pt/PI_flobo/teorica7.html http://www.di.ubi.pt/~fsilva/prog/Prog_Cap4.pdf (em 10/11/2008) Curso Profissional de Informática de Gestão - 2008/2011 - Módulo 7


Exercício Implemente a função:

char *strchr(char *str, char ch) Que devolve o endereço da primeira ocorrência de ch em s, caso não exista devolve NULL (o endereço e não o índice). Escreva um programa que solicite a string e um caracter e mostre no ecrã os caracteres da string original que se encontram a partir do caracter lido (inclusive).

RESOLUÇÃO Curso Profissional de Informática de Gestão - 2008/2011 - Módulo 7

Memória dinâmica Até agora para trabalhar com strings ou

vectores de outros tipos de dados, era absolutamente necessário saber, à partida, quantos elementos seriam necessários. Por exemplo, para criar duas strings iguais com um valor a introduzir pelo utilizador, declaram-se as duas strings com uma dimensão suficientemente grande, de tal modo que a string introduzida pelo utilizador possa ser copiada para o outro vector.

Curso Profissional de Informática de Gestão - 2008/2011 - Módulo 7


Memória dinâmica

Porque razão é que a string que irá conter a cópia tem que ser declarada com determinada dimensão? Uma vez que o seu objectivo é conter uma cópia de outra string, deve ser criada apenas depois de se saber qual o espaço ocupado pela string introduzida pelo utilizador. Curso Profissional de Informática de Gestão - 2008/2011 - Módulo 7

Memória dinâmica Poupa-se assim memória, ao evitar reservar

conjuntos elevados de memória que só seriam novamente libertados quando o programa ou a função onde foram declarados terminar. Todas as funções que tratam da alocação dinâmica de memória estão acessíveis através do ficheiro de cabeçalho stdlib.h

Curso Profissional de Informática de Gestão - 2008/2011 - Módulo 7


Alocação de memória A alocação dinâmica de memória é realizada,

normalmente, através das funções malloc e calloc. calloc void *malloc(size_t nBytes) O objectivo é criar um Bloco constituído por nBytes Bytes e devolver o endereço desse bloco.

A função malloc permite alocar o conjunto de

Bytes indicados pelo programador, devolvendo um apontador para o Bloco de Bytes criados, ou NULL caso a alocação falhe. Curso Profissional de Informática de Gestão - 2008/2011 - Módulo 7

Alocação de memória

Curso Profissional de Informática de Gestão - 2008/2011 - Módulo 7


Alocação de memória Existe outra função que permite a alocação

de memória. void *calloc(size_t num, size_t size) Esta função permite criar, dinamicamente, num elementos, cada um com dimansão size Bytes.

A função calloc permite criar num elementos,

cada um deles com o mesmo número de Bytes (size). A função coloca todos os Bytes alocados com o valor zero. Devolve o endereço da zona criada ou NULL.

Curso Profissional de Informática de Gestão - 2008/2011 - Módulo 7

Alocação de memória A função realloc permite alterar o número de

Bytes que estão presentemente associados a um bloco previamente criado utilizando a função malloc ou calloc. void *realloc(void *ptr, size_t new_size)

Curso Profissional de Informática de Gestão - 2008/2011 - Módulo 7


Alocação de memória

Curso Profissional de Informática de Gestão - 2008/2011 - Módulo 7

Alocação de memória Notas relativas a realloc realloc: Se o bloco actualmente alocado puder suportar a nova

dimensão, a memória adicional e também reservada e é retornado ptr. Se não existir espaço suficiente para prolongar o bloco, é então criado um novo bloco com a totalidade dos Bytes necessários. Os dados são copiados para a nova localização e é retornado o novo endereço. Se o parâmetro ptr é igual a NULL, então a função comporta-se como o malloc. Se, por algum motivo, não for possível a alocação de memória, ou se o número de Bytes for igual a zero é devolvido NULL. Curso Profissional de Informática de Gestão - 2008/2011 - Módulo 7


Libertar a memória A libertação da memória alocada através das

funções malloc, calloc e realloc pode ser realizada através da função: void free(void *ptr)

Curso Profissional de Informática de Gestão - 2008/2011 - Módulo 7

Exercício Implemente a função strdup que cria uma

nova string exactamente igual à que lhe foi passada por parâmetro.

char *strdup(char *s) { char * tmp = (char *) malloc(strlen(s)+1); if (tmp != NULL) strcpy(tmp, s); return tmp; }

Curso Profissional de Informática de Gestão - 2008/2011 - Módulo 7


Estruturas de dados dinâmicas Para demonstrar como se pode utilizar a memória dinâmica, vamos implementar uma estrutura clássica denominada FILA DE ESPERA. Uma fila caracteriza-se por manter a regra: “O primeiro a entrar é o primeiro a sair”. Como não sabemos à partida qual vai ser o número de indivíduos que pode ter que esperar, a fila terá que ter um crescimento dinâmico. Para tal é necessária uma estrutura composta pelos dados e por um apontador para a próxima posição, isto é, para a próxima pessoa da fila de espera. Neste caso, a fila será suportada por um apontador. PROGRAMA Curso Profissional de Informática de Gestão - 2008/2011 - Módulo 7

Bibliografia Damas, Luís; LINGUAGEM C; FCA; 2ª edição; Lisboa;

1999 Aguilar, Luis Joyanes; FUNDAMENTOS DE PROGRAMAÇÃO – Algoritmos, estruturas de dados e objetos; Mc Graw Hill; Tradução da 3ª edição; São Paulo; 2008 Azul, Artur Augusto; BASES DE PROGRAMAÇÃO 10; Porto Editora; Porto Em 10/11/2008

http://www.eisnt.com/GPSI/programacao/Aula4C.pdf http://www.linhadecodigo.com.br/Artigo.aspx?id=425 http://www.criarweb.com/artigos/825.php http://deei.fct.ualg.pt/PI_flobo/teorica7.html http://www.di.ubi.pt/~fsilva/prog/Prog_Cap4.pdf

Curso Profissional de Informática de Gestão - 2008/2011 - Módulo 7


Turn static files into dynamic content formats.

Create a flipbook
Issuu converts static files into: digital portfolios, online yearbooks, online catalogs, digital photo albums and more. Sign up and create your flipbook.