Curso de Pascal
Vetores e Matrizes


  As variáveis como os integer, string, char, real, etc são capazes de armazenar apenas um dado de cada vez para uma determinada entidade (nome, idade, nota, cargo etc). Entretanto, se desejarmos armazenar mais de um dado para a mesma entidade, como fazer?
  Para os programadores iniciantes, o programa mais intuitivo para armazenar o nome de 10 pessoas na memória é o seguinte:
var nome1, nome2, nome3, nome4, nome5, nome6, nome7, nome8, nome9, nome10 : string[40];
begin
  write('Entre o nome da 1a. pessoa: ');
  readln(nome1);
  write('Entre o nome da 2a. pessoa: ');
  readln(nome2);
  write('Entre o nome da 3a. pessoa: ');
  readln(nome3);
  write('Entre o nome da 4a. pessoa: ');
  readln(nome4);
  write('Entre o nome da 5a. pessoa: ');
  readln(nome5);
  write('Entre o nome da 6a. pessoa: ');
  readln(nome6);
  write('Entre o nome da 7a. pessoa: ');
  readln(nome7);
  write('Entre o nome da 8a. pessoa: ');
  readln(nome8);
  write('Entre o nome da 9a. pessoa: ');
  readln(nome9);
  write('Entre o nome da 10a. pessoa: ');
  readln(nome10);
end.
  O programa ficou longo e utiliza diversas variáveis. Observe que para acessar cada nome, temos que referenciar a respectiva variável. Imagine se desejássemos utilizar 1000 nomes!

  Podemos corrigir esse inconveniente e criar um programa mais simples e elegante, através do uso de vetores.


  Vetores

  O vetor é uma lista de variáveis do mesmo tipo, com um tamanho fixo e disposta sequencialmente na memória do computador.

  A sintaxe de um vetor é a seguinte:
var nome : array[inicio..fim] of tipo_de_dado

  A declaração de um vetor é semelhante à declaração da variável. A diferença está na uso da palavra reservada "array", que indica a criação de um vetor, mais os limites dele.
  Diferente do Basic e do C, onde indicamos o tamanho do vetor, no Pascal informamos o menor valor do índice (inicio), seguido do maior valor de índice (fim).

  Exemplo de criação de um vetor de valores inteiros:
var nota : array[1..10] of integer;
  É uma lista de valores inteiros, variando de 1 até 10.

  Para acessar um elemento do vetor, deve-se utilizar o nome do vetor, seguido do número da posição que desejamos ler/alterar os dados entre colchetes. Exemplo:
  nota[4] := 8.0;   { Escreve na posição 4 do vetor }
  writeln(nota[4]); { Lê e imprime o valor contido no índice 4 do vetor }

  Agora, vamos reescrever o programa dos nomes, criando um vetor do tipo string[40] para 10 nomes.
var nome : array[1..10] of string[40];
      i : integer;
begin
  for i:=1 to 10 do
  begin
    write('Entre com o nome da ',i,'a. pessoa: ');
    readln(nome[i]);
  end;
end. 
  Observe como o programa ficou mais fácil de entender e mais simples.

  O identificador array indica que queremos criar um vetor (lista), de tamanho igual a dez, numerado de 1 até (assinalado com '..') 10, e do tipo string[40].


  Referência a um vetor

  Conforme visto, a referência a uma posição da lista é sempre feita através do nome da variável de vetor, seguida de colchetes contendo o índice do vetor.
  Podemos também fazer referência diretamente ao vetor, e ter acesso total a ele. Para isso, utilizamos apenas o nome do vetor, sem os colchetes.
  Veja o exemplo a seguir e os comentários entre as chaves.
var vet1, vet2 : array[1..5] of integer;

begin
  vet1[1] := 7;  { Acessa item do vetor, na posição 1, alterando o valor para 7 }
  vet2 := vet1;  { Copia todo o vetor 1 para o vetor 2 }
end.


  Aprofundando: disposição do vetor na memória

  Um vetor nada mais é do que um agrupamento de dados do mesmo tipo, com um tamanho pré-definido. Dessa maneira, os dados estão dispostos na memória de forma contígua (em seqüência).
  De forma a ilustrar como os dados são armazenados na memória, vamos criar um vetor de números inteiros de tamanho igual a 5.
var vet : array[1..5] of integer;

  O vetor não é inicializado. Assim, se não colocarmos os valores em cada posição, teremos os valores que estiverem na memória (lixo) no momento de execução. Esses valores são aleatórios.
  Vamos atribuir um valor para cada posição do vetor "vet":
var vet : array[1..5] of integer;

begin
  vet[1] := 7;
  vet[2] := 5;
  vet[3] := 9;
  vet[4] := 8;
  vet[5] := 3;
end.

  Um variável do tipo inteiro ocupa 2 bytes na memória. Dessa forma, os dados do vetor "vet" estarão dispostos na memória da seguinte maneira:
|     1 |     2 |     3 |     4 |     5 | - Posição do vetor
|-------+-------+-------+-------+-------+
| 07 00 | 05 00 | 09 00 | 08 00 | 03 00 | - Dado na memória (valores em hexadecimal)

  Quando acessamos a posição 3 do vetor (assinalado em azul a seguir), o valor 9 é retornado.
|     1 |     2 |     3 |     4 |     5 | - Posição do vetor
|-------+-------+-------+-------+-------+
| 07 00 | 05 00 | 09 00 | 08 00 | 03 00 | - Dado na memória (valores em hexadecimal)

  Exemplos de vetores de outros tipos:

  Char:
var vet : array[1..5] of char;
|  1 |  2 |  3 |  4 |  5 | - Posição do vetor
|----+----+----+----+----+
| 75 | 82 | 28 | 10 | 49 | - Dado na memória (valores em hexadecimal)

  Real:
var vet : array[1..2] of real;
|                 1 |                 2 | - Posição do vetor
|-------------------+-------------------+
| 01 02 CD AB 10 12 | 45 55 65 75 AD A0 | - Dado na memória (valores em hexadecimal)


  Matrizes

  Podemos também criar matrizes, isto é, um vetor com n dimensões.
  Uma tabela é um exemplo de uma matriz de duas dimensões e um cubo é um exemplo de uma matriz de três dimensões.

  Para criar uma matriz, usamos também a palavra reservada "array". Para vetores multidimensionais, a sintaxe é:
var nome : array[variacao_dim_1, variacao_dim_2, ..., variacao_dim_n] of tipo_de_dado;

  Para matrizes de duas dimensões (tabela), a linha representa a dimensão 1, enquanto que a coluna representa a dimensão 2.
var matriz : array[variacao_linha, variacao_coluna] of tipo_de_dado;

  No exemplo a seguir, será criada uma tabela (matriz) que guarda o dia, o mês e o ano de nascimento de 10 pessoas. A tabela terá 10 linhas e 3 colunas.
var data : array[1..10, 1..3] of integer;

  A tabela equivalente é ilustrada a seguir.

  DIA MES ANO
PESSOA 1      
PESSOA 2      
PESSOA 3      
PESSOA 4      
PESSOA 5      
PESSOA 6      
PESSOA 7      
PESSOA 8      
PESSOA 9      
PESSOA 10      

  Obs: A área assinalada em amerelo é a informação armazenada na memória do computador. A área em verde é apenas o cabeçalho da tabela para a compreensão e localização dos dados.


  Acesso aos dados na matriz

  O acesso aos dados da matriz é feito utilizando-se o índice correspondente a cada dimensão criada, separados por vírgula e respeitando a ordem de criação.
  No exemplo da tabela anterior, fazemos o acesso ao índice da linha, depois ao da coluna:

data[linha, coluna];

  Por exemplo, para imprimir o dia de nascimento da "pessoa5", fazemos:
writeln(data[5,1]);

  O programa a seguir cadastra a data de nascimento de 10 pessoas na tabela criada.
var data : array[1..10, 1..3] of integer;
    i : integer;
begin
  for i:=1 to 10 do
  begin
    writeln('Pessoa numero ',i);
    write('Dia: ');
    read(data[i,1]);
    write('Mes: ');
    read(data[i,2]);
    write('Ano: ');
    read(data[i,3]);
  end;
end. 


 Inicialização de vetores e matrizes no Pascal

  Apesar dos compiladores de Pascal atuais aceitarem a inicialização de variáveis do tipo vetor, no Turbo Pascal isso somente é possível quando o vetor é criado como constante.
  A regra de atribuição é a seguinte:
Vetor:
(posição_1, posição_2, ..., posição_n);

Matriz NxM:
(
  (linha_1_Coluna_1, ..., linha_1_Coluna_M), 
  ..., 
  (linha_N_Coluna_1, ..., linha_N_Coluna_M)
);

  Exemplos:
const
     vetor : array[1..5] of integer = (1, 3, 5, 7, 9);
var
     i : integer;

begin
  for i:=1 to 5 do
    write(vetor[i], ' ');
end.
  Saída:
  1 3 5 7 9

const
     vetor : array[1..3,1..2] of integer = ((1, 3), (5, 7), (9,11));
var
     i, j : integer;

begin
  for i:=1 to 3 do
  begin
    for j:=1 to 2 do
      write(vetor[i,j], ' ');
    writeln;
  end;
end.
  Saída:
  1 3
  5 7
  9 11

  Os parêntesis mais internos correspondem às dimensões mais à direita do vetor. Exemplo com um cubo:
type cube = array[0..1,0..1,0..1] of integer;
const maze : cube = (((0,1),(2,3)),((4,5),(6,7)));
var i,j,k : integer;

begin
  for i:=0 to 1 do
  begin
    for j:=0 to 1 do
    begin
      for k:=0 to 1 do
        writeln(maze[i,j,k]);
    end;
  end;
end.
Adaptado de: Turbo Pascal reference manual, 1983.


  Algumas considerações

  Só podemos criar listas ou tabelas com o mesmo tipo de variável. Entretanto, é possível definir tipos de variáveis compostas (ver capítulo de tipos) e utilizá-las em vetores. Definindo um variável composta, seria possível termos um registro com o nome do tipo String, a idade do tipo inteiro e a altura do tipo real, e armazená-las em um vetor.

  O tamanho da tabela é fixo. Deve ser definido antes de rodar o programa, em sua construção.

  Podemos criar matrizes com N dimensões. Basta seguir a regra da matriz. Exemplo para 3 dimensões:
var cubo : array[1..20, 1..3, 1..50] of integer;
...
begin
  cubo[1,2,5] := 15;
end.

  Não é obrigatório o uso completo de um vetor ou matriz. Por exemplo, podemos criar uma tabela com 1000 linhas e usar somente 200. Entretanto, não podemos criar uma tabela com 200 linhas e querer utilizar 1000. Assim, o tamanho da matriz deverá ser dimensionado para o uso esperado, de forma que não haja desperdício ou falta de espaço.


  Listas de tamanho variável

  Já sabemos que o vetor não permite o redimensionamento de seu tamanho. Entretanto, é possível criar listas com o tamanho variável. Para isso, devemos criar um vetor com o tamanho máximo previsto para essa lista e utilizar somente a quantidade de campos necessários.

  Principais características:
  Inserção

  Há dois modos de inserção: o primeiro insere sempre ao final da lista, não sendo necessário o deslocamento dos elementos, enquanto que o segundo insere o elemento em uma posição P da lista, sendo necessário o deslocamento dos outros elementos, uma vez que não podemos sobrescrever sobre uma informação que já ocupa a posição P.

  Exemplo de inserção do valor "7" ao final da lista:
tamanho = 3

┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐
│ 4 │ 5 │ 9 │xxx│xxx│xxx│xxx│xxx│xxx│xxx│
└───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘
  0   1   2   3   4   5   6   7   8   9

Insere:
┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐
│ 4 │ 5 │ 9 │ 7 │xxx│xxx│xxx│xxx│xxx│xxx│
└───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘
  0   1   2   3   4   5   6   7   8   9

tamanho = 4

  Exemplo de inserção do valor "7" na posição "1" da lista:
tamanho = 3

┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐
│ 4 │ 5 │ 9 │xxx│xxx│xxx│xxx│xxx│xxx│xxx│
└───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘
  0   1   2   3   4   5   6   7   8   9

Desloca (abre espaço):
┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐
│ 4 │ 5 │ 5 │ 9 │xxx│xxx│xxx│xxx│xxx│xxx│
└───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘
  0   1   2   3   4   5   6   7   8   9
      ↑

Insere:
┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐
│ 4 │ 7 │ 5 │ 9 │xxx│xxx│xxx│xxx│xxx│xxx│
└───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘
  0   1   2   3   4   5   6   7   8   9
      ↑

tamanho = 4

  O deslocamento DEVERÁ sempre começar pelo último elemento. Se fosse começado pelo primeiro elemento a ser deslocado, ele sobrescreveria o próximo elemento.
┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐
│ 4 │ 5 │ 9 │xxx│xxx│xxx│xxx│xxx│xxx│xxx│
└───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘
  0   1   2   3   4   5   6   7   8   9
Procedimento correto:
┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐
│ 4 │ 5 │ 9 │ 9 │xxx│xxx│xxx│xxx│xxx│xxx│
└───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘
  0   1   2   3   4   5   6   7   8   9
          ---->

┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐
│ 4 │ 5 │ 5 │ 9 │xxx│xxx│xxx│xxx│xxx│xxx│
└───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘
  0   1   2   3   4   5   6   7   8   9
      ---->
Procedimento Errado:
┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐
│ 4 │ 5 │ 5 │xxx│xxx│xxx│xxx│xxx│xxx│xxx│
└───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘
  0   1   2   3   4   5   6   7   8   9
      ---->

┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐
│ 4 │ 5 │ 5 │ 5 │xxx│xxx│xxx│xxx│xxx│xxx│
└───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘
  0   1   2   3   4   5   6   7   8   9
          ---->


  Remoção

  Há dois modos de remoção: o primeiro remove sempre ao final da lista, não sendo necessário o deslocamento dos elementos, enquanto que o segundo remove o elemento em uma posição P da lista, sendo necessário o deslocamento dos outros elementos.

  Exemplo de remoção do último elemento da lista:
tamanho = 4

┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐
│ 4 │ 5 │ 9 │ 7 │xxx│xxx│xxx│xxx│xxx│xxx│
└───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘
  0   1   2   3   4   5   6   7   8   9
              ↑

Remove:
┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐
│ 4 │ 5 │ 9 │ 7 │xxx│xxx│xxx│xxx│xxx│xxx│
└───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘
  0   1   2   3   4   5   6   7   8   9
          ↑

tamanho = 3

  Exemplo de remoção do item da posição "1" da lista:
tamanho = 3

┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐
│ 4 │ 5 │ 9 │xxx│xxx│xxx│xxx│xxx│xxx│xxx│
└───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘
  0   1   2   3   4   5   6   7   8   9
          ↑

Desloca:
┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐
│ 4 │ 9 │ 9 │xxx│xxx│xxx│xxx│xxx│xxx│xxx│
└───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘
  0   1   2   3   4   5   6   7   8   9
      ↑

tamanho = 2

  Em ambos os casos, o "lixo" permanece na antiga última posição. Entretanto, o tamanho da lista diminuiu e esse "lixo" é ignorado.

  Diferente da inserção, o deslocamento agora deverá começar pelo primeiro elemento a ser deslocado.


  Programa completo

  O programa a seguir demonstra o uso de uma lista com tamanho variável.
const v : array[1..10] of byte = ( 4,5,9,0,0,0,0,0,0,0 );

var total : byte;

procedure push(valor : byte);
begin
  if (total>= 10) then
    exit;

  total := succ(total);
  v[total] := valor;
end;

procedure insere(valor, pos : byte);
var i : byte;
begin
  if ((total>= 10) or (pos < 1) or (pos >= total)) then
    exit;

  for i:=total downto pos do
    v[i+1] := v[i];

  v[pos] := valor;
  total := succ(total);
end;

procedure pop;
begin
  if (total<=0) then
    exit;

  total := pred(total);
end;

procedure remove(pos : byte);
var i : byte;
begin

  if ((total<= 0) or (pos < 1) or (pos > total)) then
    exit;

  for i:=pos+1 to total do
    v[i-1] := v[i];

  total := pred(total);
end;

procedure imprime;
var i : byte;
begin
  for i:=1 to total do
    write(v[i], ' ');
  writeln;
end;

begin
  total := 3;
  imprime;
  push(7);
  imprime;
  insere(6,2);
  imprime;
  pop;
  imprime;
  remove(1);
  imprime;
end.
  Saída:
  4 5 9
  4 5 9 7
  4 6 5 9 7
  4 6 5 9
  6 5 9



<< Anterior Pascal Próxima >>


/MARMSX/CURSOS/PASCAL