Ponteiros em Pascal Variáveis ponteiros são aquelas que guardam o endereço de outra, possibilitando o acesso a seu conteúdo. Declaração em Pascal: var ptInt: ^integer; {ponteiro para uma variável inteira } ptReal: ^real; {ponteiro para uma variável real}
Operador unário que obtém o endereço de uma variável Operador unário que obtém o endereço de uma variável program soma; var S,A,B:integer; PtS,PtA,PtB : ^integer; begin readln(A,B); PtA := @A; PtB := @B; PtS := @S; PtS^ := PtA^ + PtB^; writeln('Resultado: ',PtS^); end.
Alocação de memória PtA PtB PtS A B S program soma; var S,A,B: integer; PtS,PtA,PtB: ^integer; begin A := 2; B := 3; PtA := @A; PtB := @B; PtS := @S; PtS^ := PtA^ + PtB^; Writeln('Resultado: ',PtS^); end. PtA PtB PtS A B S
Alocação de memória PtA PtB PtS A 2 B S program soma; var S,A,B: integer; PtS,PtA,PtB: ^integer; begin A := 2; B := 3; PtA := @A; PtB := @B; PtS := @S; PtS^ := PtA^ + PtB^; Writeln('Resultado: ',PtS^); end. PtA PtB PtS A 2 B S
Alocação de memória PtA PtB PtS A 2 B 3 S program soma; var S,A,B: integer; PtS,PtA,PtB: ^integer; begin A := 2; B := 3; PtA := @A; PtB := @B; PtS := @S; PtS^ := PtA^ + PtB^; Writeln('Resultado: ',PtS^); end. PtA PtB PtS A 2 B 3 S
Alocação de memória PtA PtB PtS A 2 B 3 S program soma; var S,A,B: integer; PtS,PtA,PtB: ^integer; begin A := 2; B := 3; PtA := @A; PtB := @B; PtS := @S; PtS^ := PtA^ + PtB^; Writeln('Resultado: ',PtS^); end. PtA PtB PtS A 2 B 3 S
Alocação de memória PtA PtB PtS A 2 B 3 S program soma; var S,A,B: integer; PtS,PtA,PtB: ^integer; begin A := 2; B := 3; PtA := @A; PtB := @B; PtS := @S; PtS^ := PtA^ + PtB^; Writeln('Resultado: ',PtS^); end. PtA PtB PtS A 2 B 3 S
Alocação de memória PtA PtB PtS A 2 B 3 S program soma; var S,A,B: integer; PtS,PtA,PtB: ^integer; begin A := 2; B := 3; PtA := @A; PtB := @B; PtS := @S; PtS^ := PtA^ + PtB^; Writeln('Resultado: ',PtS^); end. PtA PtB PtS A 2 B 3 S
Alocação de memória PtA PtB PtS A 2 B 3 S 5 program soma; var S,A,B: integer; PtS,PtA,PtB: ^integer; begin A := 2; B := 3; PtA := @A; PtB := @B; PtS := @S; PtS^ := PtA^ + PtB^; Writeln('Resultado: ',PtS^); end. PtA PtB PtS A 2 B 3 S 5
Alocação de memória 5 PtA PtB PtS A 2 B 3 S 5 program soma; var S,A,B: integer; PtS,PtA,PtB: ^integer; begin A := 2; B := 3; PtA := @A; PtB := @B; PtS := @S; PtS^ := PtA^ + PtB^; Writeln('Resultado: ',PtS^); end. PtA PtB PtS A 2 B 3 S 5
procedure New( ) Cria dinamicamente (em tempo de execução) uma nova variável e faz uma variável ponteiro apontar para ela. type Str18 = string[18]; var P: ^Str18; begin New(P); P^ := 'Bom dia!'; Writeln (P^) Dispose(P); end.
Alocação de memória type Str18 = string[18]; var P: ^Str18; begin New(P); P^ := 'Bom dia!'; Writeln (P^) Dispose(P); end. P
Alocação de memória type Str18 = string[18]; var P: ^Str18; begin New(P); P^ := 'Bom dia!'; Writeln (P^) Dispose(P); end. P
Alocação de memória type Str18 = string[18]; var P: ^Str18; begin New(P); P^ := 'Bom dia!'; Writeln (P^) Dispose(P); end. P Bom Dia!
Alocação de memória Bom Dia! type Str18 = string[18]; var P: ^Str18; begin New(P); P^ := 'Bom dia!'; Writeln (P^) Dispose(P); end. P Bom Dia!
OBS: a procedure Dispose libera uma variável criada Alocação de memória type Str18 = string[18]; var P: ^Str18; begin New(P); P^ := 'Bom dia!'; Writeln (P^) Dispose(P); end. P OBS: a procedure Dispose libera uma variável criada dinamicamente. Se isso não for feito, a região de memória disponibilizada não poderá ser usada até que o computador seja reiniciado.
Outras situações comuns Um ponteiro recebendo o endereço de um outro: var p,q,r: ^integer; begin new(p); p^ := 5; new(q); q:= p; r := p; {ou q} writeln(p^); { ou q^ ou, ainda, r^ } dispose(q^); { ou p^ ou, ainda, r^ } :
Alocação de memória : p q r var p,q,r: ^integer; begin new(p); new(q); q:= p; r := p; {ou q} writeln(p^);{ou q^ ou r^ } dispose(q^);{ou p^ ou r^ } : p q r
Alocação de memória : p q r var p,q,r: ^integer; begin new(p); new(q); q:= p; r := p; {ou q} writeln(p^);{ou q^ ou r^ } dispose(q^);{ou p^ ou r^ } : p q r
Alocação de memória : p q r 5 var p,q,r: ^integer; begin new(p); new(q); q:= p; r := p; {ou q} writeln(p^);{ou q^ ou r^ } dispose(q^);{ou p^ ou r^ } : p q r 5
Alocação de memória : p q r 5 var p,q,r: ^integer; begin new(p); new(q); q:= p; r := p; {ou q} writeln(p^);{ou q^ ou r^ } dispose(q^);{ou p^ ou r^ } : p q r 5
Alocação de memória : p q r 5 var p,q,r: ^integer; begin new(p); new(q); q:= p; r := p; {ou q} writeln(p^);{ou q^ ou r^ } dispose(q^);{ou p^ ou r^ } : p q r 5
Alocação de memória : p q r 5 var p,q,r: ^integer; begin new(p); new(q); q:= p; r := p; {ou q} writeln(p^);{ou q^ ou r^ } dispose(q^);{ou p^ ou r^ } : p q r 5
Alocação de memória 5 : p q r 5 var p,q,r: ^integer; begin new(p); new(q); q:= p; r := p; {ou q} writeln(p^);{ou q^ ou r^ } dispose(q^);{ou p^ ou r^ } : p q r 5
Portanto, o manuseio de ponteiros Alocação de memória ATENÇÃO: observe que a partir de q:=p;, perdeu-se o acesso à variável criada com new(q); Portanto, o manuseio de ponteiros exige cuidado! var p,q,r: ^integer; begin new(p); p^ := 5; new(q); q:= p; r := p; {ou q} writeln(p^);{ou q^ ou r^ } dispose(q^);{ou p^ ou r^ } : p q r
Listas encadeadas Em várias situações em programação temos que lidar com listas de elementos cujo tamanho exato é desconhecido. Soluções: Empregar um agregado homogêneo (array) superdimensionado. 1 2 3 ... N-1 N Empregar seqüências de células (nós) que contêm dois elementos: um valor e um ponteiro para o próximo nó. ... p /
Quando adotar uma ou outra solução? Agregado homogêneo: quando pudermos determinar com segurança o tamanho máximo. Listas encadeada: - quando for difícil estimar o tamanho máximo com segurança; e/ou... - quando se desejar maior agilidade nas inclusões ou exclusões de novos elementos.
Lista: uma estrutura recursiva: Ex: definição de uma lista de inteiros: Lista vazia; Um inteiro seguido de uma lista de inteiros. OBS: o ponteiro contido no primeiro nó aponta para a lista formada pelos demais nós p / 4 7 1 9 Lista vazia Lista com quatro elementos (o último quarda o ponteiro nil)
Lista: uma estrutura recursiva: Ex: definição de uma lista de inteiros: Lista vazia; Um inteiro seguido de uma lista de inteiros. OBS: para se ter acesso aos elementos da lista é necessário que haja sempre uma variável ponteiro apontando para a “cabeça” da lista (primeiro elemento) p / 4 7 1 9 Lista vazia Lista com quatro elementos (o último quarda o ponteiro nil)
Lista: uma estrutura recursiva: Ex: definição de uma lista de inteiros: Lista vazia; Um inteiro seguido de uma lista de inteiros. A partir de cada nó, pode-se ter acesso ao seguinte. Assim, pode-se percorrer a lista toda. p / 4 7 1 9 Lista vazia Lista com quatro elementos (o último quarda o ponteiro nil)
Lista: uma estrutura recursiva: Ex: definição de uma lista de inteiros: Lista vazia; Um inteiro seguido de uma lista de inteiros. Quando a lista estiver vazia o ponteiro que deveria apontar o primeiro elemento, guarda o valor nil ( / ). p / 4 7 1 9 Lista vazia Lista com quatro elementos (o último quarda o ponteiro nil)
Definição (recursiva) de um nó: OBS: no início da execução do programa só há ponteiros (p,q) para nós. Estes poderão, dinamicamente, ser empregados para se construir uma lista. Definição (recursiva) de um nó: type tDado = integer; { ou real, char, etc.} tPtNo = ^tNo; tNo = record Dado:tDado; Prox :tPtNo; end; var p,q: tPtNo;
p^.Dado Exemplo de uso: criação de uma lista com dois elementos: var p,q: tPtNo; begin new(p); p^.Dado := 7; new(q); q^.Dado := 3; p^.Prox := q; q^.Prox := nil; : p^.Dado acesso ao objeto apontado por p campo específico
p^.Prox Exemplo de uso: criação de uma lista com dois elementos: var p,q: tPtNo; begin new(p); p^.Dado := 7; new(q); q^.Dado := 3; p^.Prox := q; q^.Prox := nil; : p^.Prox acesso ao objeto apontado por p campo específico
Alocação de memória var p,q: tPtNo; begin new(p); p^.Dado := 7; new(q); q^.Dado := 3; p^.Prox := q; q^.Prox := nil; : p q
Alocação de memória var p,q: tPtNo; begin new(p); p^.Dado := 7; new(q); q^.Dado := 3; p^.Prox := q; q^.Prox := nil; : p q
Alocação de memória var p,q: tPtNo; begin new(p); p^.Dado := 7; new(q); q^.Dado := 3; p^.Prox := q; q^.Prox := nil; : p q 7
Alocação de memória var p,q: tPtNo; begin new(p); p^.Dado := 7; new(q); q^.Dado := 3; p^.Prox := q; q^.Prox := nil; : p q 7
Alocação de memória var p,q: tPtNo; begin new(p); p^.Dado := 7; new(q); q^.Dado := 3; p^.Prox := q; q^.Prox := nil; : p q 7 3
Alocação de memória var p,q: tPtNo; begin new(p); p^.Dado := 7; new(q); q^.Dado := 3; p^.Prox := q; q^.Prox := nil; : p q 7 3
Alocação de memória var p,q: tPtNo; begin new(p); p^.Dado := 7; new(q); q^.Dado := 3; p^.Prox := q; q^.Prox := nil; : p q 7 3 /
Exemplo 2: dada a lista abaixo, inserir um novo nó entre os dois existentes e armazenar nele o valor 2. : new(q); q^.Dado := 2; q^.Prox := p^.Prox; p^.Prox := q; q := nil; p q 7 3 /
Alocação de memória : new(q); q^.Dado := 2; q^.Prox := p^.Prox; p^.Prox := q; q := nil; p q 7 3 /
Alocação de memória : new(q); q^.Dado := 2; q^.Prox := p^.Prox; p^.Prox := q; q := nil; p q 7 3 /
Alocação de memória : new(q); q^.Dado := 2; q^.Prox := p^.Prox; p^.Prox := q; q := nil; p q 2 7 3 /
Alocação de memória : new(q); q^.Dado := 2; q^.Prox := p^.Prox; p^.Prox := q; q := nil; p q 2 7 3 /
Alocação de memória : new(q); q^.Dado := 2; q^.Prox := p^.Prox; p^.Prox := q; q := nil; p q 2 7 3 /
Alocação de memória : new(q); q^.Dado := 2; q^.Prox := p^.Prox; p^.Prox := q; q := nil; p q / 2 7 3 /
Alocação de memória : new(q); q^.Dado := 2; q^.Prox := p^.Prox; p^.Prox := q; q := nil; p q / 7 2 3 /
Manuseio de listas encadeadas Para tratar de forma genérica todas as possíveis manipulações de uma lista encadeada, é definido um conjunto de rotinas. Exemplos: inserir/excluir um elemento no início inserir /excluir um elemento no final inserir /excluir um elemento na enésima posição calcular a soma dos elementos
Exemplo: inserir elemento V no final Duas situações a se considerar: Lista vazia Lista com 1 ou mais elementos p p / ... /
Para lista vazia: p / : new(p); p^.Dado:=V; p^.Prox:=nil;
Alocação de memória : new(p); p^.Dado:=V; p^.Prox:=nil; V 5 p
Alocação de memória : new(p); p^.Dado:=V; p^.Prox:=nil; V 5 p
Alocação de memória : new(p); p^.Dado:=V; p^.Prox:=nil; V 5 p 5
Alocação de memória : new(p); p^.Dado:=V; p^.Prox:=nil; V 5 p 5 /
Para lista não vazia: p 4 7 1 / : { fazer q apontar para o último elemento } q:= p; while q^.Prox <> nil do q:=q^.Prox; { inserir o novo elemento } new(r); r^.Dado:=V; r^.Prox:=nil; q^.Prox:=r;
Alocação de memória : V 5 p q r 7 2 3 q:= p; while q^.Prox <> nil do q:=q^.Prox; new(r); r^.Dado:=V; r^.Prox:=nil; q^.Prox:=r; V 5 p q r 7 2 3 /
Alocação de memória : V 5 p q r 7 2 3 q:= p; while q^.Prox <> nil do q:=q^.Prox; new(r); r^.Dado:=V; r^.Prox:=nil; q^.Prox:=r; V 5 p q r 7 2 3 /
Alocação de memória : V 5 p q r 7 2 3 q:= p; while q^.Prox <> nil do q:=q^.Prox; new(r); r^.Dado:=V; r^.Prox:=nil; q^.Prox:=r; V 5 p q r 7 2 3 /
Alocação de memória : V 5 p q r 7 2 3 q:= p; while q^.Prox <> nil do q:=q^.Prox; new(r); r^.Dado:=V; r^.Prox:=nil; q^.Prox:=r; V 5 p q r 7 2 3 /
Alocação de memória : V 5 p q r 7 2 3 q:= p; while q^.Prox <> nil do q:=q^.Prox; new(r); r^.Dado:=V; r^.Prox:=nil; q^.Prox:=r; V 5 p q r 7 2 3 /
Alocação de memória : V 5 p q r 7 2 3 q:= p; while q^.Prox <> nil do q:=q^.Prox; new(r); r^.Dado:=V; r^.Prox:=nil; q^.Prox:=r; V 5 p q r 7 2 3 /
Alocação de memória : V 5 p q r 7 2 3 q:= p; while q^.Prox <> nil do q:=q^.Prox; new(r); r^.Dado:=V; r^.Prox:=nil; q^.Prox:=r; V 5 p q r 7 2 3 /
Alocação de memória : V 5 p q r 7 2 3 q:= p; while q^.Prox <> nil do q:=q^.Prox; new(r); r^.Dado:=V; r^.Prox:=nil; q^.Prox:=r; V 5 p q r 7 2 3 /
Alocação de memória : V 5 p q r 7 2 3 5 q:= p; while q^.Prox <> nil do q:=q^.Prox; new(r); r^.Dado:=V; r^.Prox:=nil; q^.Prox:=r; V 5 p q r 7 2 3 / 5
Alocação de memória : V 5 p q r 7 2 3 5 q:= p; while q^.Prox <> nil do q:=q^.Prox; new(r); r^.Dado:=V; r^.Prox:=nil; q^.Prox:=r; V 5 p q r 7 2 3 / 5 /
Alocação de memória : V 5 p q r 7 2 3 5 q:= p; while q^.Prox <> nil do q:=q^.Prox; new(r); r^.Dado:=V; r^.Prox:=nil; q^.Prox:=r; V 5 p q r 7 2 3 5 /
Juntando as duas situações... Como existe a possibilidade de p mudar seu conteúdo, ele é passado por referência. procedure InsereNo(var p: tPtNo; V : tDado); var q,r: tPtNo; begin new(r); r^.Dado:=V; r^.Prox:=nil; if p = nil then p:= r else begin q:= p; while q^.Prox <> nil do q:=q^.Prox; q^.Prox:=r; end;