Page 1
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}
Page 2
Operador @ 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.
Page 3
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.
Alocação de memória
A B
PtA
S
PtB
PtS
Page 4
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.
Alocação de memória
A 2 B
PtA
S
PtB
PtS
Page 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.
Alocação de memória
A 2 B 3
PtA
S
PtB
PtS
Page 6
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.
Alocação de memória
A 2 B 3
PtA
S
PtB
PtS
Page 7
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.
Alocação de memória
A 2 B 3
PtA
S
PtB
PtS
Page 8
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.
Alocação de memória
A 2 B 3
PtA
S
PtB
PtS
Page 9
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.
Alocação de memória
A 2 B 3
PtA
S 5
PtB
PtS
Page 10
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.
Alocação de memória
A 2 B 3
PtA
S 5
PtB
PtS
5
Page 11
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.
Page 12
type Str18 = string[18];var P: ^Str18;begin New(P); P^ := 'Bom dia!'; Writeln (P^) Dispose(P); end.
Alocação de memória
P
Page 13
type Str18 = string[18];var P: ^Str18;begin New(P); P^ := 'Bom dia!'; Writeln (P^) Dispose(P); end.
Alocação de memória
P
Page 14
type Str18 = string[18];var P: ^Str18;begin New(P); P^ := 'Bom dia!'; Writeln (P^) Dispose(P); end.
Alocação de memória
P
Bom Dia!
Page 15
type Str18 = string[18];var P: ^Str18;begin New(P); P^ := 'Bom dia!'; Writeln (P^) Dispose(P); end.
Alocação de memória
P
Bom Dia!
Bom Dia!
Page 16
type Str18 = string[18];var P: ^Str18;begin New(P); P^ := 'Bom dia!'; Writeln (P^) Dispose(P); end.
Alocação de memória
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.
Page 17
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^ } :
Page 18
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^ } :
Alocação de memória
p
q
r
Page 19
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^ } :
Alocação de memória
p
q
r
Page 20
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^ } :
Alocação de memória
p
q
r
5
Page 21
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^ } :
Alocação de memória
p
q
r
5
Page 22
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^ } :
Alocação de memória
p
q
r
5
Page 23
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^ } :
Alocação de memória
p
q
r
5
Page 24
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^ } :
Alocação de memória
p
q
r
5
5
Page 25
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^ } :
Alocação de memória
p
q
r
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!
Page 26
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
/
Page 27
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.
Page 28
Lista: uma estrutura recursiva:
Ex: definição de uma lista de inteiros:
• Lista vazia;
• Um inteiro seguido de uma lista de inteiros.
p
/4 7 1 9
/ p
Lista vazia Lista com quatro elementos(o último quarda o ponteiro nil)
OBS: o ponteiro contido noprimeiro nó aponta para a lista formada
pelos demais nós
Page 29
Lista: uma estrutura recursiva:
Ex: definição de uma lista de inteiros:
• Lista vazia;
• Um inteiro seguido de uma lista de inteiros.
p
/4 7 1 9
/ p
Lista vazia Lista com quatro elementos(o último quarda o ponteiro nil)
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 (primeiroelemento)
Page 30
Lista: uma estrutura recursiva:
Ex: definição de uma lista de inteiros:
• Lista vazia;
• Um inteiro seguido de uma lista de inteiros.
p
/4 7 1 9
/ p
Lista vazia Lista com quatro elementos(o último quarda o ponteiro nil)
A partir de cada nó, pode-se ter acesso ao seguinte.Assim, pode-se percorrer a lista toda.
Page 31
Lista: uma estrutura recursiva:
Ex: definição de uma lista de inteiros:
• Lista vazia;
• Um inteiro seguido de uma lista de inteiros.
p
/4 7 1 9
/ p
Lista vazia Lista com quatro elementos(o último quarda o ponteiro nil)
Quando a lista estiver vazia o ponteiro que deveria apontar o primeiro elemento, guarda o valor nil ( / ).
Page 32
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;
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.
Page 33
var
p,q: tPtNo;
begin
new(p);
p^.Dado := 7;
new(q);
q^.Dado := 3;
p^.Prox := q;
q^.Prox := nil;
:
Exemplo de uso: criação de uma lista com dois elementos:
p^.Dadoacesso ao
objeto apontado por p
acesso ao campo
específico
Page 34
var
p,q: tPtNo;
begin
new(p);
p^.Dado := 7;
new(q);
q^.Dado := 3;
p^.Prox := q;
q^.Prox := nil;
:
Exemplo de uso: criação de uma lista com dois elementos:
p^.Proxacesso ao
objeto apontado por p
acesso ao campo
específico
Page 35
var
p,q: tPtNo;
begin
new(p);
p^.Dado := 7;
new(q);
q^.Dado := 3;
p^.Prox := q;
q^.Prox := nil;
:
Alocação de memória
p
q
Page 36
var
p,q: tPtNo;
begin
new(p);
p^.Dado := 7;
new(q);
q^.Dado := 3;
p^.Prox := q;
q^.Prox := nil;
:
Alocação de memória
p
q
Page 37
var
p,q: tPtNo;
begin
new(p);
p^.Dado := 7;
new(q);
q^.Dado := 3;
p^.Prox := q;
q^.Prox := nil;
:
Alocação de memória
p
q
7
Page 38
var
p,q: tPtNo;
begin
new(p);
p^.Dado := 7;
new(q);
q^.Dado := 3;
p^.Prox := q;
q^.Prox := nil;
:
Alocação de memória
p
q
7
Page 39
var
p,q: tPtNo;
begin
new(p);
p^.Dado := 7;
new(q);
q^.Dado := 3;
p^.Prox := q;
q^.Prox := nil;
:
Alocação de memória
p
q
7 3
Page 40
var
p,q: tPtNo;
begin
new(p);
p^.Dado := 7;
new(q);
q^.Dado := 3;
p^.Prox := q;
q^.Prox := nil;
:
Alocação de memória
p
q
7 3
Page 41
var
p,q: tPtNo;
begin
new(p);
p^.Dado := 7;
new(q);
q^.Dado := 3;
p^.Prox := q;
q^.Prox := nil;
:
Alocação de memória
p
q
7 3 /
Page 42
:
new(q);
q^.Dado := 2;
q^.Prox := p^.Prox;
p^.Prox := q;
q := nil;
:
Exemplo 2: dada a lista abaixo, inserir um novo nó entre os dois existentes e armazenar nele o valor 2.
p
7 3 /
q
Page 43
:
new(q);
q^.Dado := 2;
q^.Prox := p^.Prox;
p^.Prox := q;
q := nil;
:
Alocação de memória
p
7 3 /
q
Page 44
:
new(q);
q^.Dado := 2;
q^.Prox := p^.Prox;
p^.Prox := q;
q := nil;
:
Alocação de memória
p
7 3 /
q
Page 45
:
new(q);
q^.Dado := 2;
q^.Prox := p^.Prox;
p^.Prox := q;
q := nil;
:
Alocação de memória
p
7 3 /
q
2
Page 46
:
new(q);
q^.Dado := 2;
q^.Prox := p^.Prox;
p^.Prox := q;
q := nil;
:
Alocação de memória
p
7 3 /
q
2
Page 47
:
new(q);
q^.Dado := 2;
q^.Prox := p^.Prox;
p^.Prox := q;
q := nil;
:
Alocação de memória
p
7 3 /
q
2
Page 48
:
new(q);
q^.Dado := 2;
q^.Prox := p^.Prox;
p^.Prox := q;
q := nil;
:
Alocação de memória
p
7 3 /
q
/
2
Page 49
:
new(q);
q^.Dado := 2;
q^.Prox := p^.Prox;
p^.Prox := q;
q := nil;
:
Alocação de memória
p
7 3 /
q
/
2
Page 50
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
Page 51
Exemplo: inserir elemento V no final
Duas situações a se considerar:
Lista vazia Lista com 1 ou mais elementos
p
/
/ p
...
Page 52
Para lista vazia: / p
:
new(p);
p^.Dado:=V;
p^.Prox:=nil;
Page 53
: new(p);
p^.Dado:=V;
p^.Prox:=nil;
Alocação de memória
p
V
5
Page 54
: new(p);
p^.Dado:=V;
p^.Prox:=nil;
Alocação de memória
p
V
5
Page 55
: new(p);
p^.Dado:=V;
p^.Prox:=nil;
Alocação de memória
p
V
5
5
Page 56
: new(p);
p^.Dado:=V;
p^.Prox:=nil;
Alocação de memória
p
V
5
5 /
Page 57
Para lista não vazia:
:
{ 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;
p
4 7 1 /
Page 58
: q:= p;
while q^.Prox <> nil do
q:=q^.Prox;
new(r);
r^.Dado:=V;
r^.Prox:=nil;
q^.Prox:=r;
Alocação de memória
p
7 3 /
q
2
r
V
5
Page 59
: q:= p;
while q^.Prox <> nil do
q:=q^.Prox;
new(r);
r^.Dado:=V;
r^.Prox:=nil;
q^.Prox:=r;
Alocação de memória
p
7 3 /
q
2
r
V
5
Page 60
: q:= p;
while q^.Prox <> nil do
q:=q^.Prox;
new(r);
r^.Dado:=V;
r^.Prox:=nil;
q^.Prox:=r;
Alocação de memória
p
7 3 /
q
2
r
V
5
Page 61
: q:= p;
while q^.Prox <> nil do
q:=q^.Prox;
new(r);
r^.Dado:=V;
r^.Prox:=nil;
q^.Prox:=r;
Alocação de memória
p
7 3 /
q
2
r
V
5
Page 62
: q:= p;
while q^.Prox <> nil do
q:=q^.Prox;
new(r);
r^.Dado:=V;
r^.Prox:=nil;
q^.Prox:=r;
Alocação de memória
p
7 3 /
q
2
r
V
5
Page 63
: q:= p;
while q^.Prox <> nil do
q:=q^.Prox;
new(r);
r^.Dado:=V;
r^.Prox:=nil;
q^.Prox:=r;
Alocação de memória
p
7 3 /
q
2
r
V
5
Page 64
: q:= p;
while q^.Prox <> nil do
q:=q^.Prox;
new(r);
r^.Dado:=V;
r^.Prox:=nil;
q^.Prox:=r;
Alocação de memória
p
7 3 /
q
2
r
V
5
Page 65
: q:= p;
while q^.Prox <> nil do
q:=q^.Prox;
new(r);
r^.Dado:=V;
r^.Prox:=nil;
q^.Prox:=r;
Alocação de memória
p
7 3 /
q
2
r
V
5
Page 66
: q:= p;
while q^.Prox <> nil do
q:=q^.Prox;
new(r);
r^.Dado:=V;
r^.Prox:=nil;
q^.Prox:=r;
Alocação de memória
p
7 3 /
q
2
r
V
5
5
Page 67
: q:= p;
while q^.Prox <> nil do
q:=q^.Prox;
new(r);
r^.Dado:=V;
r^.Prox:=nil;
q^.Prox:=r;
Alocação de memória
p
7 3 /
q
2
r
V
5
5 /
Page 68
: q:= p;
while q^.Prox <> nil do
q:=q^.Prox;
new(r);
r^.Dado:=V;
r^.Prox:=nil;
q^.Prox:=r;
Alocação de memória
p
7 3
q
2
r
V
5
5 /
Page 69
Juntando as duas situações...
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;
end;
Como existe a possibilidade de p mudar seu conteúdo, ele é passado por referência.