




                                CAPTULO 7          
            
                           REGISTROS E CONJUNTOS  
            
            
            7.1. REGISTROS          
            
                 Um registro  (record)  uma estrutura de dados que pode    
            juntar vrios tipos de dados em um nico tipo. Devido a essa
            propriedade, um  registro costuma  ser classificado  como um
            tipo de  dado heterogneo.  Os tipos que compem um registro
            so chamados campos.        
                 A declarao  de um  registro normalmente  feita em um
            bloco  de  delaraes  TYPE,  e  inicia-se  com  o  nome  do
            registro, seguido  de um  sinal de  igualdade e  da  palavra
            chave RECORD,  dos nomes  dos campos  e respectivos tipos, e
            encerra-se com um END.
            
                                NomeDoRegistro = RECORD
                                  campo1: tipo1;
                                  campo2: tipo2;
                                  ...     ...
                                END;
            
                 Para se  ter acesso  a um  campo de um registro deve-se
            fazer referncia  ao  nome  da  varivel  do  tipo  registro
            seguido de um ponto e do nome do campo.
                 Registros so  usados quando  vrios  dados,  de  tipos
            distintos ou no, tm alguma relao entre si.
            
            Exemplo: O  endereo de  uma casa   feita atravs de vrias
            informaes de  tipos  diferentes:  nome  da  rua  (string),
            nmero da  casa (integer),  C.E.P. (longint), nome da cidade
            (string) e  estado (string). Claramente h uma forte relao
            entre esses  dados, de  forma que  seria conveniente  pensar
            neles como  se fossem  uma nica informao. Temos assim uma
            situao em  que o  mais natural  seria declarar um registro
            ENDEREO formado  pelo agrupamento  de  todos  esses  outros
            tipos simples:
            
                                TYPE
                                  endereco = RECORD
                                    rua: string[30];
                                    numero: integer;
                                    CEP: longint;
                                    cidade: string[20];
                                    estado: string[2];
                                  END;
            
                 Tipos iguais  podem ser  declarados de uma s vez em um
            registro. Neste  exemplo, se  eliminssemos a  limitao  no
            tamanho das  variveis do tipo string, poderamos declarar o
            tipo endereo na forma:
            

                                        - 97 -





                                TYPE
                                  endereco = RECORD
                                    rua, cidade, estado: string;
                                    numero: integer;
                                    CEP: longint
                                  END;
            
                 Quando no   especificado  o tamanho de um string, ele
            fica sendo  255. Assim, a ltima declarao do tipo endereo
            gasta mais  memria que a primeira. No existe uma ordem nos
            campos de  um  registro,  isto  ,  no  importa  quem  seja
            declarado primeiro ou por ltimo.
            
                 Suponhamos que  x,  y  sejam  duas  variveis  do  tipo
            endereco:
                                VAR
                                  x, y: endereco;
            
                 Uma forma  de se  atribuir valores aos campos de x pode
            ser:
                           x.rua := 'Av. Epitacio Pessoa';
                           x.numero := 9876;
                           x.CEP := 58000;
                           x.cidade := 'Joao Pessoa';
                           x.estado := 'PB';
            
                 Os campos  de um  registro tambm  podem ser  definidos
            atravs  de   comandos  de   leitura,  como   por   exemplo,
            Readln(x.rua) ou Read(x.cidade).
                 Assim, sempre  que nos  referirmos s cinco informaes
            que  formam   o  endereo   acima,  poderemos   nos  referir
            simplesmente ao  endereco x. Se quisssemos que o endereo y
            fosse uma  cpia do  endereo x,  ento bastaria  uma  nica
            atribuio:
                                     y := x;
            
            Exemplo: As  principais informaes que identificam um aluno
            so o  nome, a  matrcula e  o nmero  do curso.  Como estas
            informaes esto  intimamente relacionadas,    conveniente
            definir um registro com esses campos:
            
                           TYPE
                             aluno = RECORD
                               nome: string[30];
                               matricula: string[8];
                               curso: byte
                             END;
            
                 Poderamos  desejar   um  registro  mais  completo  que
            inclusse tambm  o telefone  do aluno  e  seu  endereco.  
            possvel um  campo de um registro ser uma estrutura bastante
            complicada,  e  em  particular,  pode  ser  outro  registro.
            Acrescentaremos ento  um campo  RESIDENCIA do tipo endereco
            (definido anteriormente) ao registro aluno:

                                        - 98 -





            
                           TYPE
                             aluno = RECORD
                               nome: string[30];
                               matricula: string[8];
                               curso: byte;
                               telefone: string[15];
                               residencia: endereco
                             END;
            
                 Suponhamos que  Aluno1 seja uma varivel do tipo aluno.
            Ento Aluno1 poderia ser definida assim:
            
                           Aluno1.nome := 'Maria I. de Souza';
                           Aluno1.matricula := '9221001X';
                           Aluno1.curso := 29;
                           Aluno1.telefone := '(083) 441-1522';
            
                 O campo  RESIDENCIA de  ALUNO1 tambm    um  registro.
            Logo, devemos mencionar os nomes de cada um dos seus campos:
            
                           Aluno1.residencia.rua := 'Joao V. Carneiro'
                           Aluno1.residencia.numero := '146'
                           Aluno1.residencia.CEP := '58840'
                           Aluno1.residencia.cidade := 'Pombal'
                           Aluno1.residencia.estado := 'PB'
            
                 Se ENDER  fosse uma varivel do tipo endereco associado
            ao Aluno1, poderamos ter a seguinte atribuio:
            
                           Aluno1.residencia := ender;
            
                 A grande  utilidade do tipo registro  poder se referir
            a vrios  tipos  de  dados  como  se  fosse  um  nico  dado
            (heterogneo).  Dessa   forma,  acreditamos   que      mais
            conveniente se  referir a  todas as  informaes acima  como
            sendo simplesmente  "Aluno1",  do  que  se  referir  a  cada
            informao separadamente.
                 Definir os  campos  de  um  registro,    o  mesmo  que
            preencher uma folha com os mesmos tipos de informaes:
            
            +-------------------NOME---------------------+--MATRICULA--+
            |                                            |             |
            +-----------------------RUA-----------------------+-NUMERO-+
            |                                                 |        |
            +-------------------------------------------------+--------+
            
            Exemplo: O  comando WITH  permite  alguma  simplificao  na
            definio de um registro. Um comando como
                                WITH Nome_Var DO
                                BEGIN
                                  ...
                                END;

                                        - 99 -





            permite o  acesso direto  aos campos do registro NOME_VAR em
            qualquer comando  que esteja  dentro da rea delimitada pelo
            BEGIN/END do WITH.
                 Na  definicao   do  registro   x  anterior,  poderamos
            escrever:
            
                           WITH x DO
                           BEGIN
                             rua := 'Av. Epitacio Pessoa';
                             numero := 9876;
                             CEP := 58000;
                             cidade := 'Joao Pessoa';
                             estado := 'PB'
                           END;
            
            e no caso do ALUNO1 anterior, temos:
            
                           WITH Aluno1 DO
                           BEGIN
                             nome := 'Maria I. de Souza';
                             matricula := '9221001X';
                             curso := 29;
                             telefone := '(083) 441-1522';
                             WITH residencia DO
                             BEGIN
                               rua := 'Joao V. Carneiro'
                               numero := '146'
                               CEP := '58840'
                               cidade := 'Pombal'
                               estado := 'PB'
                             END
                           END;
            
            Exemplo: Observe  a definio  da seguinte  funo distncia
            entre dois pontos (a, b, c) e (x, y, z) do R^3:
            
               FUNCTION Distancia(a, b,  x, y, z: real): real;
            
               BEGIN
                 Distancia := Sqrt(Sqr(a - x) + Sqr(b - y) + Sqr(c - z))
               END;
            
                 Ela funciona  perfeitamente bem,  s que tem parmetros
            demais. Olhando  seu cabealho,  parece at  que ela calcula
            uma distncia  entre 6  pontos. Neste  caso, a, b, c deveria
            ser um  nico dado,  assim como  x, y,  z. A  soluo  usar
            registros.  Definimos   um   registro   chamado   PONTO,   e
            redefinimos a funo distncia da seguinte forma:
            
            TYPE
              ponto = record
                x, y, z: real
              end;
            

                                       - 100 -





            FUNCTION Distancia(P, Q: ponto): real;
            
            BEGIN
              Distancia := Sqrt(Sqr(P.x - Q.x) + Sqr(P.y - Q.y) +
                                Sqr(P.z - Q.z))
            END;
            
                 A lgica do programa deve deixar claro que os campos x,
            y, z  do registro  PONTO referem-se s primeiras, segundas e
            terceiras coordenadas.
            
            Exemplo:  O  bloco  TYPE  a  seguir  define  vrias  figuras
            geomtricas como  sendo registros.  Alm de  sua posio  na
            tela, o  registro tambm contm informao a respeito da cor
            da figura.
            
                           TYPE
                             PontoDoPlano = record
                               x, y: real
                             end;
            
                             Reta = record
                               p, q: PontoDoPlano;
                               cor: byte
                             end;
            
                             Circunferencia = record
                               centro: PontoDoPlano;
                               raio: real;
                               cor: byte
                             end;
            
                             Triangulo = record
                               a, b, c: PontoDoPlano;
                               cor: byte
                             end;
            
                 Por exemplo,  uma circunferncia C de raio 3, centro na
            origem e cor verde, deve ser definida assim:
            
                           VAR
                             C: circunferencia;
            
                           ...
                           C.centro.x := 0;
                           C.centro.y := 0;
                           C.raio := 3;
                           C.cor := green;
            
                 Como outro  exemplo, um  tringulo T  com vrtices  nos
            pontos (1,  2), (3,  -1) e (4, 7) e de cor vermelha, poderia
            ser definido como a seguir:
            
            

                                       - 101 -





                           VAR
                             T: triangulo;
            
                           ...
                           T.a.x := 1; T.a.y := 2;
                           T.b.x := 3; T.b.y := -1;
                           T.c.x := 4; T.c.y := 7;
                           T.cor := red;
            
            Observao: A declarao de um registro pode ser feita em um
            bloco de  declaraes VAR,  ao  invs  do  bloco  TYPE.  Por
            exemplo, a  declarao da  circunferncia C anterior poderia
            ter sido feita assim:
            
                           VAR
                             C: record
                                  centro: record
                                            x, y: real;
                                          end;
                                  raio: real;
                                  cor: byte;
                                end;
            
                 Achamos a  utilizao de  um bloco  TYPE mais legvel e
            muitas vezes se mostra mais til.
            
            7.2. CONJUNTOS      
            
                 Um  conjunto  (set)    uma  coleo  de  variveis  ou
            constantes dos  tipos char,  byte, enumerado  definido  pelo
            usurio ou subtipos destes.
                 A declarao  de um  conjunto   feita  pelas  palavras
            chave SET  OF, seguidas  do nome  do tipo  dos elementos  do
            conjunto (tipo base).
            
            Exemplo: TYPE
                       Numeros = SET OF byte;    (* conj. de inteiros *)
                       Maiusculas = SET OF 'A'..'Z';  (* conj. de letras
                                                         maiusculas   *)
                       Caracteres = SET OF char;     (* conj. de char *)
                       cor = (verde, amarelo, vermelho);
                       ArcoIris = SET OF cor;       (* conj. de cores *)
            
                 Um conjunto  definido listando-se seus elementos entre
            colchetes e separados por vrgulas ou listando-se intervalos
            entre colchetes.
            
            Exemplo: Considerando  ainda os  tipos do  exemplo anterior,
            definamos as seguintes variveis:
            
                            VAR
                              vogais: Maiusculas;
                              A, B: numeros;
                              X, Y: Caracteres;

                                       - 102 -





            
                 So vlidas as seguintes atribuies:
            
                 vogais := ['A', 'E', 'I', 'O', 'U'];
                 A := [1..10]; (* = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] *)
                 B := [11..200];
                 X := ['*', '+', '-', '/', '^'];
                 Y := [ ]; (* conjunto vazio *)
            
                 So vlidas  as seguintes  operaes com  conjuntos:  +
            (unio), *  (interseo), -  (diferena),  e  os  operadores
            relacionais = (igual), <> (diferente), <= (est contido), >=
            (contm)  e  IN (pertence).
            
            Exemplo: ['A', 'B'] + ['B', 'C'] = ['A', 'B', 'C']
                     ['A', 'B'] * ['B', 'C'] = ['B']
                     [1..100] + [101..200] = [1..200]
                     ['a'..'z'] * ['A'..'Z'] = [ ]
                     [1..10] - [3..7] = [1, 2, 8, 9, 10]
            
                     [10..20] = [11..19]            ---> FALSE
                     ['x', 'y'] = ['y', 'x']        ---> TRUE
                     [10..20] >= [11..19]           ---> TRUE
                     [ ] <= [1, 2, 3, 4]            ---> TRUE
                     ['a'] + ['b'] <> ['a', 'b']    ---> FALSE
                     1 IN [0..100]                  ---> TRUE
                     '*' IN ['A'..'Z'] + ['a'..'z'] ---> FALSE
            
                 O uso  de conjuntos  bastante limitado. No  possvel
            se  usar  comandos  de  entrada  ou  sada  diretamente  com
            conjuntos. Nestes  casos, deve-se usar um FOR para entrar ou
            listar  cada   elemento  separadamente.  Tambm  no  existe
            comando pr-definido  para contar  a quantidade de elementos
            de um conjunto.
            
            Exemplo:  O  fragmento  a  seguir,  verifica  se  uma  opo
            (caracter) digitada no teclado  vlida ou no.
            
                      CONST
                        OpcaoValida: SET OF char = ['f', 'q', 'r'];
                      ...
                      op := ReadKey;
                      IF op IN OpcaoValida THEN
                        Writeln('Opcao valida: ', op)
                      ELSE
                        Writeln('Opcao invalida: ', op);
                      ...
            
                 Neste caso,  o uso de conjuntos poderia ser evitado com
            um IF mais extenso:
                      IF (op = 'f') OR (op = 'q') OR (op = 'r') THEN...
            
            Exemplo: No  presente exemplo,  os elementos  de um conjunto
            so listados na tela e contados.

                                       - 103 -





            
            PROGRAM ContandoElementos;
            
            TYPE
              conjunto = SET OF byte;
            
            VAR
              X: conjunto;
              i, cont: byte;
            
            BEGIN
              (* Definicao do conjunto X *)
              X := [1, 3, 5, 7, 11, 13, 17, 19, 23, 101];
            
              cont := 0; (* contador de elementos do conjunto *)
              Writeln('Elementos do conjunto X: ');
              for i := 0 to 255 do
                if i IN X then
                begin
                  Write(i:5);
                  Inc(cont); (* o mesmo que cont := cont + 1 *)
                end;
              Writeln;
              Writeln('O conjunto X tem ', cont, ' elementos.');
            END.
            
                  preciso  que o FOR varra todo o tipo base do conjunto
            para se descobrir quais so os elementos do conjunto.
                 O procedimento pr-definido INC(x) incrementa o inteiro
            x de uma unidade;  o mesmo que x := x + 1.
            
            Exemplo: Neste  exemplo, definimos  uma funo  que testa se
            dois  strings   tm  os   mesmos  caracteres.  Por  exemplo,
            Compara('AMAR', 'OMAR')  = TRUE  e  Compara('PB',  'Pb')  =
            FALSE.
            
            FUNCTION Compara(a, b: string): boolean;
            
            VAR
              x, y: SET OF char;
              i: byte;
            
            BEGIN
              x := [ ];                       (* x e' o somatorio, ou *)
              for i := 1 to Length(a) do      (* seja, uniao dos con- *)
                x := x + [a[i]];         (* juntos unitarios formados *)
                                         (* pelos caracteres de a     *)
            
              y := [ ];                       (* y e' formado pelos   *)
              for i := 1 to Length(b) do      (* caracteres de b      *)
                y := y + [b[i]];
            
              Compara := (x = y)
            END;

                                       - 104 -
