Ŀ
VI - Tipos de dados estruturados 


VI.1 - Introduo
       ----------

    At  o  presente   instante, ns definimos dados do tipo simples ou no
    estruturados,  como  por  exemplo: Byte, Integer, Real, Char e Boolean.
    No  entanto,   existem   outros  tipos  de  dados chamados complexos ou
    estruturados, String   um deles.  Ns  j falamos sobre o tipo de dado
    estruturado  String, por ser extremamente utilizado como j salientamos
    antes. Mas o Turbo  Pascal  possui outros tipos de estruturas, a saber:

	- Array
	- Record
	- Set
	- File
	- String ( j visto )

    O  tipo  file refere-se a arquivos de discos e ser amplamente estudado
    num captulo  parte. Os demais sero vistos neste captulo.


VI.2 - Array
       -----

    Imagine que ns precisemos declarar 100 variveis do tipo integer, isso
    poderia ser feito da seguinte forma:

        Var i1,i2,i3,i4,...,i100 : Integer;

    Embora  isso  parea  uma  brincadeira (de mal gosto),   possvel. Mas
    podemos  tambm  dizer  que   um grande incmodo. E se alm dessas 100
    variveis,  precisarmos  tambm 1000 do tipo Char ou 2000 ou ... . Como
    podemos ver, as coisas podem se complicar. Mas  para  quem  acessa BBS,
    coisa de louco, ento o cara pode achar MUITO LEGAL. (:-))


VI.2.1 - Arrays unidimensionais

    Turbo Pascal nos fornece um tipo de dado estruturado chamado Array, que
    nos permite criar um grande nmero de variveis de determinado tipo,sem
    os incovenientes anteriores.

    Exemplo 1:

    Type Arranjo = Array[1..100] of Integer;

    Var  i : Arranjo;

    ou

    Var i : Array[1..100] of Integer;

    Aps  a   declarao  acima,  teramos  definidas 100 variveis do tipo
    Integer, cujos nomes seriam:

            i[1] - i[2] - i[3] - . . . - i[100]
 
    Exemplo 2:

    Type
      faixa   = 1..2000;
      Arranjo = Array[faixa] Of Char;

    Var
      Arranjo_simples : Arranjo;

    Aps  as  declaraes  acima, teramos definidas 2000 variveis do tipo
    char com o nome Arranjo_simples.

    Exemplos:

    ---------------------------------------------------------
    Program Exemplo_1;
    Uses Crt;

    (********************************************************
     L 10 nmeros inteiros do teclado e os escreve na tela
     ao contrrio do que foram lidos
    ********************************************************)

    Type faixa   = 1..10;
         arranjo = Array[faixa] Of Integer;

    Var  a : arranjo;
         i : Integer;

    Begin
       ClrScr;
       For i:=1 to 10 do
          Begin
             Write('a[',i:2,'] = ');
             Readln(a[i]);
          End;
       ClrScr;
       For i:=10 downto 1 do writeln(a[i]);
    End.
    ---------------------------------------------------------
    Program Exemplo_2;
    Uses CRT;

    (********************************************************
     Programa que le no mximo 100 nmeros reais do teclado
     e os coloca em ordem crescente
    ********************************************************)

    Const Num_max = 100;

    Type  faixa   = 1..Num_max;
          arranjo = Array[faixa] of Real;

    Var   i,j,n : Integer;
          a     : arranjo;
          z     : Real;

    Begin
       ClrScr;
       Writeln('Ordenacao de numeros lidos do teclado':40+19);
                                {escreve no  meio da linha}
       Writeln;Writeln; { pula duas linhas }
       n:=0;
       Writeln('digite um no. menor que 0 para terminar':40+19);
       Writeln;Writeln;
       Repeat
          n:=n+1;
          Write('a[',n:3,'] = ');
          Readln(a[n]);
       Until (n=Num_max) Or (a[n]<0);
       n:=n-1; { elimina o ultimo no. lido pois e' negativo }
       ClrScr;
       For i:=1 to n-1 Do
          For j:=i+1 to n Do
             If a[i] >= a[j]
                Then Begin
                        z:=a[i];
                        a[i]:=a[j];
                        a[j]:=z;
                     End;
       For i:=1 to n Do Writeln(a[i]:10:2);
    end.
    ---------------------------------------------------------
    Program Exemplo_3;
    Uses CRT;

    (********************************************************
     Programa semelhante ao anterior s que coloca em ordem
     crescente nomes lidos do teclado
    ********************************************************)

    Const Num_max = 100;

    Type  faixa   = 1..Num_max;
          nomes   = String[30];
          arranjo = Array[faixa] of nomes;

    Var   i,j,n : Integer;
          a     : arranjo;
          z     : nomes;

    Begin
       ClrScr;
       Writeln('Ordenacao de nomes lidos do teclado':40+19);
                                        {escreve no meio da linha}
       Writeln;Writeln; { pula duas linhas }
       n:=0;
       Writeln('digite um nome = a zero para terminar':40+19);
       Writeln;Writeln;
       Repeat
          n:=n+1;
          Write('a[',n:3,'] = ');
          Readln(a[n]);
       Until (n=Num_max) Or (a[n]='0');
       n:=n-1; { elimina o ultimo nome lido pois e' zero }
       ClrScr;
       For i:=1 to n-1 Do
          For j:=i+1 to n Do
             If a[i] >= a[j]
                Then Begin
                        z:=a[i];
                        a[i]:=a[j];
                        a[j]:=z;
                     End;
       For i:=1 to n Do Writeln(a[i]:30);
    end.
    ---------------------------------------------------------
    Program Exemplo_4;
    Uses CRT;

    (********************************************************
     Programa que l as notas de alunos de uma determinada
     classe e depois lista os alunos e as respectivas notas
     menores que 5.0
    ********************************************************)

    Const
              No_de_alunos = 30;

    Type
              Classe = Array[1..No_de_alunos] Of Real;

    Var
              n : Integer;
              a : Classe;

    Begin
       ClrScr;
       For n:=1 to No_de_alunos Do
          Begin
             Write('Aluno no. ',n:2,' ---> ');
             Readln(a[n]);
          End;
       ClrScr;
       Writeln('Alunos com media menor que 5':40+15);
       Writeln('numero  nota');
       For n:=1 to No_de_alunos Do
          If a[n]<5
             Then Writeln(n:2,a[n]:10:1);
    End.
    ---------------------------------------------------------


VI.2.2 - Arrays Multidimensionais

    No item anterior, trabalhamos com Arrays unidimensionais, ou  seja,  de
    uma  dimenso.  No  entanto,  possvel trabalhar com arrays de mais de
    uma  dimenso  e  nesses casos, eles so chamados de multidimensionais.

    Exemplos:

    Var a : array[1..10,2..5] Of Integer;

    Na  declarao  acima,  definimos um Array de 40 elementos chamado 'a'.
    Ele   constitudo  de  10  linhas  numeradas  de  1 a 10 por 4 colunas
    numeradas de 2 a 5. O acesso a cada elemento  feito da seguinte forma:

    a[1,2]   a[1,3] ...   a[1,5]
    a[2,2]   a[2,3] ...   a[2,5]
    ...      ...    ...   ...
    a[10,2]  a[10,3] ...  a[10,5]

    Poderamos definir o mesmo array da seguinte forma:

    Var a : array[1..10] of array[2..5] Of Integer;

    Ou da seguinte forma:

    Type b = array[2..5] Of Integer;

    Var a : array[1..10] Of b;

    Podemos  tambm  definir arrays de maior nmero de dimenses pelo mesmo
    processo, exemplo:

    Var a : array[1..5,1..6,1..7] Of Integer;

    Exemplo:
    ---------------------------------------------------------
    Program Exemplo;
    Uses CRT;

    (********************************************************
     Programa Matriz --> Tem a finalidade de ler uma matriz
     do teclado e em seguida multiplicar uma coluna ou linha
     por uma constante. Neste programa, procurei utilizar o
     maior nmero possvel de conceitos dados at aqui
     ********************************************************)

    (* definio das constantes do programa *)

    Const NUM_MAX_COL = 20; (* nmero mximo de colunas *)
          NUM_MAX_LIN = 10; (* nmero mximo de linhas  *)

    Var a           : array[1..NUM_MAX_LIN,1..NUM_MAX_COL] of integer;
        i,j,k,p,
        nl,nc       : integer;
        lc          : char;

    Begin
       ClrScr;
           (* l o nmero de linhas da matriz *)
       Repeat
          Write('Numero de linhas da matriz ----------> ');
          Readln(nl);
       Until nl<=NUM_MAX_LIN;
           (* l o nmero de colunas da matriz *)
       Repeat
          Write('Numero de colunas da matriz ---------> ');
          Readln(nc);
       Until nc<=NUM_MAX_COL;
           (* l a constante de multiplicao *)
       Write('Constante para multiplicacao --------> ');
       Readln(k);
           (* pergunta se  uma coluna ou linha para ser multiplicada *)
       Repeat
          Write('Coluna ou linha para mult. (c/l) ----> ');
          Readln(lc);
       Until (lc='c') Or (lc='l');
           (* pergunta pelo nmero da coluna ou da linha a ser
                                multiplicada *)
       If lc='c'
       Then Repeat
               Write('Numero da coluna para a multip. -----> ');
               Readln(p);
            Until p<=nc
       Else Repeat
               Write('Numero da linha para a multip. ------> ');
               Readln(p);
            Until p<=nl;
       Writeln;
       TextBackGround(7);
       TextColor(15+16);
       Gotoxy(24,7);
       Write('Entre com os elementos da matriz');
       textcolor(8);
       For i:=1 to nl do
          for j:=1 to nc do
             Begin
                gotoxy(8*j,i+8);
                Write('+');
             End;
       TextBackGround(0);
       Textcolor(13);
              (* l os elementos da matriz *)
       For i:=1 to nl do
          for j:=1 to nc do
             Begin
                gotoxy(8*j,i+8);
                Read(a[i,j]);
             End;
             (* faz a multiplicao da coluna ou da linha *)
       if lc='c'
          Then for i:=1 to nl do a[i,p]:=a[i,p]*k
          Else for j:=1 to nc do a[p,j]:=a[p,j]*k;
       TextBackGround(0);
       TextColor(15+16);
       Gotoxy(24,7);
            (* apresenta o resultado final na tela *)
       Write('........Resultado final.........');
       textcolor(13);
       For i:=1 to nl do
          for j:=1 to nc do
             Begin
                gotoxy(8*j,i+8);
                Write(a[i,j]);
             End;
    End.
    ---------------------------------------------------------


VI.3 - Tipo Record
       -----------

VI.3.1 - Conceito de estrutura heterognea

    At  o presente momento, trabalhamos com estruturas que envolvem  dados
    do  mesmo  tipo.  O tipo Record nos permite criar um tipo de dado que 
    composto de itens de vrios tipos. Estes itens dos quais  o tipo Record
     formado recebem o nome de campos.

    Imaginem  que  queiramos armazenar os seguintes dados a respeito de uma
    pessoa:

                Nome - Idade - Sexo - Altura

    At  o momento,  no temos nenhum tipo de varivel capaz de fazer isso,
    pois  como podemos reparar, os quatros itens so de tipos diferentes, a
    saber:

            Nome ---> String
            Idade --> Integer
            Sexo ---> Char
            Altura -> Real

    Como veremos a seguir, o tipo Record  resolver-nos- o problema.


VI.3.2 - Definio de Records

    A  definio  de  uma   varivel  do tipo record, comea com a  palavra
    reservada Record, a qual  seguida pelos campos (variveis) e  os  seus
    tipos. A palavra reservada End seguida de um ponto e vrgula, termina a
    definio do Record. Exemplo:

    Var Nome_Do_Registro : Record
                            Nome    : String[30];
                            Idade   : Integer;
                            Sexo    : Char;
                            Altura  : Real;
                           End;

    OU

    Type Registro = Record
                       Nome    : String[30];
                       Idade   : Integer;
                       Sexo    : Char;
                       Altura  : Real;
                    End;

    Var Nome_Do_Registro : Registro;


VI.3.3 - Acesso aos elementos da estrutura.

    Para  acessarmos  os  elementos  da  estrutura, ou seja, os campos, ns
    devemos incluir o nome da  varivel seguida de um ponto e depois o nome
    do campo, exemplos:

    Nome_Do_Registro.Altura := 1.78;
    Nome_Do_Registro.Sexo   := 'M';
    Etc...

    Exemplos:
    ---------------------------------------------------------
    Program Exemplo_1;
    Uses CRT;

    (********************************************************
     L uma varivel do tipo record do teclado e em seguida a
     mostra no monitor
    ********************************************************)

    Type Pessoas = Record
                      Nome    : String[30];
                      Idade   : Integer;
                      Sexo    : Char;
                      Altura  : Real;
                   End;

    Var p : Pessoas;

    Begin
       ClrScr;
       Write('Nome ------> ');
       Readln(p.Nome);
       Write('Idade -----> ');
       Readln(p.Idade);
       Write('Sexo ------> ');
       Readln(p.Sexo);
       Write('Altura ----> ');
       Readln(p.Altura);
       Writeln;
       Writeln('Voce digitou os seguintes dados :');
       Writeln;Writeln;
       Writeln(p.nome);
       Writeln(p.idade);
       Writeln(p.sexo);
       Writeln(p.altura:6:2);
    End.
    ---------------------------------------------------------

    Podemos tambm definir arrays de records, vejam o exemplo abaixo:

    ---------------------------------------------------------
    Program Exemplo_2;
    Uses CRT;

    (********************************************************
     Programa para ler dados de no mximo 20 pessoas. Em
     seguida  feita uma listagem em ordem alfabtica pelo
     nome
    ********************************************************)

    Label fim;

    Type Pessoas = Record
                      Nome    : String[30];
                      Idade   : Integer;
                      Sexo    : Char;
                      Altura  : Real;
                   End;

    Var p     : array[1..20] of Pessoas;
        i,x,y : Integer;
        s     : Pessoas;

    Begin
       ClrScr;
       i:=0;
       Repeat
          i:=i+1;
          Write('Nome (0=fim) -> ');
          Readln(p[i].Nome);
          if p[i].Nome='0' then goto fim;
          Write('Idade --------> ');
          Readln(p[i].Idade);
          Write('Sexo ---------> ');
          Readln(p[i].Sexo);
          Write('Altura -------> ');
          Readln(p[i].Altura);
          Writeln;
    fim:
       Until ((p[i].Nome='0') or (i=20));
       If i<20 then i:=i-1;
       For x:=1 to i-1 do
          For y:=x+1 to i do
             If ((p[x].nome) >= (p[y].nome))
                then begin
                        s:=p[x];
                        p[x]:=p[y];
                        p[y]:=s;
                     End;
       ClrScr;
       Writeln('NOME':30,'IDADE':6,'SEXO':5,'ALTURA':8);
       For x:=1 to i do
          Writeln(p[x].nome:30,p[x].idade:6,p[x].sexo:5,p[x].altura:8:2);
    End.
    ---------------------------------------------------------


VI.3.4 - Declarao With

    Se existe uma srie de campos de uma varivel do tipo record   que ser
    acessada repetidamente, pode ser cansativo ter que escrever o  nome  da
    varivel na frente do campo diversas  vezes.  Para resolver o problema,
    podemos utilizar a declarao With. Sua forma :

    WITH Varivel_do_tipo_record DO comando;

    ou

    WITH Varivel_do_tipo_record DO
        Begin
            comando_1;
            comando_2;
            . . .
        End;

    Exemplo:
    ---------------------------------------------------------
    Program Exemplo_1;
    Uses CRT;

    { le uma variavel tipo record e em seguida a mostra }

    Type Pessoas = Record
                      Nome    : String[30];
                      Idade   : Integer;
                      Sexo    : Char;
                      Altura  : Real;
                   End;

    Var p : Pessoas;

    Begin
       ClrScr;
       With p do
          Begin
             Write('Nome ------> ');
             Readln(Nome);
             Write('Idade -----> ');
             Readln(Idade);
             Write('Sexo ------> ');
             Readln(Sexo);
             Write('Altura ----> ');
             Readln(Altura);
             Writeln;
             Writeln('Voce digitou os seguintes dados :');
             Writeln;Writeln;
             Writeln(nome);
             Writeln(idade);
             Writeln(sexo);
             Writeln(altura:6:2);
         End;
    End.
    ---------------------------------------------------------


VI.4 - Tipo Set
       --------

VI.4.1 - Definio e declarao

    Na   matemtica,   usamos   uma   linguagem  no  s  adequada s  suas
    necessidades,  mas  tambm  ao estudo de outras cincias. Uma boa parte
    dessa linguagem vem da teoria de conjuntos.

    Em matemtica, definimos um conjunto como sendo uma coleo de objetos,
    nomes, nmeros etc. Chamamos de elementos aos  objetos,  nomes, nmeros
    etc. que pertencem a esse conjunto.

    Pois bem, na linguagem Pascal, tambm podemos utilizar estes conceitos.
    Na  linguagem   Pascal,  um   conjunto   uma   coleo  de   elementos
    semelhantes. O tamanho do conjunto pode ser varivel, sendo que no caso
    especfico do Turbo Pascal, o conjunto pode ter no mximo 256 elementos.

    Um conjunto pode consistir em zero ou mais elementos do mesmo tipo base
    que, obrigatoriamente dever ser um tipo simples, podendo  ser qualquer
    escalar com exceo do REAL.

    Em Pascal, os conjuntos tm  seus  elementos  inclusos   em colchetes e
    separados por vrgulas. Podemos ter tambm a representao da sub-faixa.
    Exemplos:

    [1,3,5,7,9,11,13]       - alguns inteiros
    [3..7]                  - inteiros entre 3 e 7
    [3,4,5,6,7]             - equivalente  ao anterior
    ['A'..'Z']              - caracteres alfabticos maisculos
    [gol,passat,fusca]      - marcas de carro
    []                      - conjunto vazio

    Declarao

    A forma geral para definio de conjuntos :

    Type
        <identificador> = SET OF <tipo base>;

    Exemplos:

    Type
        caracteres        = set of Char;
        letras_maisculas = set of 'A'..'Z';
        dgitos           = set of 0..9;
        carros            = set of (fusca,gol,escort,opala);

    Var c       : caracteres;
        letras  : letras_maisculas;
        nmeros : dgitos;
        marca   : carros;

                        etc.


VI.4.2 -  Operaes em tipos Set

    Atribuio:

    O   operador  de   atribuio   o  mesmo utilizado para tipos simples,
    exemplos:

    c := ['a','e','i','o','u'];
    letras := ['B'..'H'];
    nmeros := [0,3,5];
                            etc.

    Unio:

    O  operador  unio   representado  pelo sinal '+'. A unio entre  dois
    conjuntos resulta num terceiro conjunto, constitudo dos elementos  dos
    dois conjuntos. Exemplo:

    a := [1,2,3];
    b := [2,3,4,5];
    c := a+b;           resulta  c = [1,2,3,4,5]

    Interseco:

    Representada  pelo  sinal '*'.  A  interseco  entre  dois  conjuntos,
    resulta num terceiro conjunto, constitu-do pelos elementos que  fazem
    parte tanto de um como do outro conjunto. Exemplo:

    a := [1,2,3];
    b := [2,3,4,5];
    c := a*b;           resulta  c = [2,3]

    Diferena:

    Representada pelo sinal '-'. Retorna um conjunto, cujos elementos esto
    num conjunto mas no no outro.

    a := [1,2,3,6];
    b := [2,3,4,5];
    c := a-b;           resulta  c = [1,6]
    c := b-a;           resulta  c = [4,5]

    Operadores relacionais:

    a =  b  todos elementos esto em ambos conjuntos
    a <> b  alguns ou todos elementos no esto em ambos conjuntos
    a >= b  todos elementos de b esto em a
    a <= b  todos elementos de a esto em b
    a IN b  a  um elemento do conjunto b

    Neste ltimo   caso,  a  deve  ser  um  elemento do mesmo tipo base  do
    conjunto b.

    Exemplos de programas:
    ---------------------------------------------------------
    Program Exemplo_1;
    Uses CRT;

    (********************************************************
     L uma tecla e a envia para o monitor at que se digite
     'S' ou 's' ou 'N' ou 'n'
    ********************************************************)

    Var tecla : Char;

    Begin
       ClrScr;
       Repeat
          Read(kbd,tecla);
          Write(tecla);
       Until tecla IN ['s','S','n','N'];
    End.
    ---------------------------------------------------------
    Program Exemplo_2;
    Uses CRT;

    (********************************************************
     l uma tecla e diz se  nmero, letra maiscula ou letra
     minscula at que se leia um '?'
    ********************************************************)

    Type simbolos = Set of Char;

    Var Maiusc,Minusc,Numeros : simbolos;
        tecla : char;

    Begin
       ClrScr;
       Maiusc  := ['A'..'Z'];
       Minusc  := ['a'..'z'];
       Numeros := ['0'..'9'];
       Repeat
          Read(kbd,tecla);
          If tecla IN Maiusc
             Then Writeln('MAIUSCULA')
             Else if tecla IN minusc
                     Then Writeln('minuscula')
                     else if tecla IN numeros
                             Then Writeln('numero')
                             else Writeln('nada');
       Until tecla = '?';
    End.
    ---------------------------------------------------------
    Program Exemplo_3;
    Uses CRT;

    (********************************************************
     Programa que conta o nmero de vogais, nmero de
     consoantes e de brancos numa frase lida do teclado
    ********************************************************)

    Type simbolos = set of char;

    Var Alfabeto,vogais,consoantes : simbolos;
        frase : string[50];
        v,c,b,x : integer;

    Begin
       Vogais:=['a','e','i','o','u','A','E','I','O','U'];
       alfabeto:=['a'..'z']+['A'..'Z'];
       consoantes:=alfabeto-vogais;
       Clrscr;
       Write('Digite uma frase --> ');
       Readln(frase);
       b:=0;c:=0;v:=0;
              (* a funo length() devolve o nmero de caracteres que o
                 parmetro tem *)
       For x:=1 to length(frase) do
          if frase[x] in vogais
             then v:=v+1
             else if frase[x] in consoantes
                     then c:=c+1
                     else if frase[x] = ' ' then b:=b+1;
       Writeln;
       writeln(b,' brancos');
       Writeln(c,' consoantes');
       Writeln(v,' vogais');
    End.
    ---------------------------------------------------------
