|
MC102 |
| REGISTROS |
Registros são variáveis que podem guardar mais de um dado, inclusive de tipos diferentes. Por exemplo, suponha que queremos trabalhar com datas, no formato dia, mês e ano. Como faríamos? Uma alternativa é transformar nossa data em dias (ou meses ou anos) e então, após termos trabalhado com ela, transformar novamente para dia, mês e ano. Trabalhoso, não? Seria muito mais fácil se pudéssemos trabalhar no formato dia, mês e ano. Como fazemos isso?
TYPE meses = (jan, fev, mar, abr, mai, jun, jul, ago, set, out, nov, dez);
dias = 1..31;
VAR data : RECORD
dia : dias;
mes : meses;
ano : integer
END;
|
Aqui definimos uma variável do tipo "data", que é um registro composto de 3 campos: dia, do tipo "dias"; mes, do tipo "meses" e ano, do tipo integer.
Assim, quando temos várias variáveis que dizem respeito à mesma coisa, as agrupamos em um registro.
Também, podemos criar um tipo com registros:
TYPE meses = (jan, fev, mar, abr, mai, jun, jul, ago, set, out, nov, dez);
dias = 1..31;
datas = RECORD
dia : dias;
mes : meses;
ano : integer
END;
VAR data : datas
|
Como sempre esse segundo enfoque é melhor, pois se precisarmos passar uma data como parâmetro de função ou procedimento ou como retorno de função fazemos
PROCEDURE Q(d : datas); FUNCTION F1(l : datas) : boolean; FUNCTION F2(l : datas) : datas; |
uma vez que o seguinte não é permitido
PROCEDURE Q(d : RECORD dia : dias; mes : meses; ano : integer END;);
FUNCTION F1(l : RECORD dia : dias; mes : meses; ano : integer END;) : boolean;
FUNCTION F2(l : RECORD dia : dias; mes : meses; ano : integer END;) :
RECORD dia : dias; mes : meses; ano : integer END;
|
Como foi dito, os campos de um registro podem ser de qualquer tipo, inclusive outro registro.
A forma geral de um registro é:
RECORD
campo1 : tipo1;
campo2 : tipo2;
campo3 : tipo1;
...
campon : tipon
END;
|
Voltando à nossa data, como carregamos um valor na nossa variável? O segmento a seguir inicializa data com 26 de outubro de 2002:
data.dia := 26; data.mes := out; data.ano := 2002; |
Ou seja, acessamos o campo de uma variável do tipo record fazendo:
nome_da_variável.campo |
E para ler o valor de um registro? Fazemos da mesma forma que atribuímos, o conjunto nome_da_variável.campo pode ser usado como uma variável comum de tipo igual ao tipo do campo:
PROGRAM P;
TYPE meses = (jan, fev, mar, abr, mai, jun, jul, ago, set, out, nov, dez);
dias = 1..31;
datas = RECORD
dia : dias;
mes : meses;
ano : integer
END;
VAR data : datas;
BEGIN
data.dia := 26;
data.mes := out;
data.ano := 2002;
write(data.dia,'/',Ord(data.mes)+1,'/',data.ano);
IF data.ano>0 THEN writeln(' d.C.')
ELSE writeln(' a.C.')
END.
|
O programa acima escreve "26/10/2003 d.C.". Viu? Podemos usar o conjunto nome_da_variável.campo como variáveis comuns.
Um outro detalhe, como o campo "ano" é integer, ele é tratado como integer:
PROGRAM P;
TYPE meses = (jan, fev, mar, abr, mai, jun, jul, ago, set, out, nov, dez);
dias = 1..31;
datas = RECORD
dia : dias;
mes : meses;
ano : integer
END;
VAR data : datas;
FUNCTION quad(x : integer) : integer;
BEGIN
quad := x*x
end;
BEGIN
data.dia := 26;
data.mes := out;
data.ano := 2002;
write(data.dia,'/',Ord(data.mes)+1,'/',data.ano);
IF data.ano>0 THEN writeln(' d.C.')
ELSE writeln(' a.C.');
data.ano := quad(data.ano) {data.ano recebe 4008004 (2002 × 2002)}
END.
|
Vejamos alguns exemplos:
Somar tempos: suponha que tenhamos dois tempos no formato hora, minuto e seguindo e queiramos somá-los, dando a resposta em hora, minuto e segundos, como faremos?
Primeiro criamos um registro para o tempo:
TYPE tempo = RECORD
hora : integer;
min : word;
seg : word
END;
|
Quem é esse word? Word é um tipo inteiro do Pascal, que vai de 0 a 65535.
Agora, fazemos o programa:
PROGRAM P;
TYPE tempo = RECORD
hora : integer;
min : word;
seg : word
END;
VAR t1 : tempo;
t2 : tempo;
t3 : tempo;
BEGIN
write('hora: ');
readln(t1.hora);
write('minuto: ');
readln(t1.min);
write('segundo: ');
readln(t1.seg);
write('hora: ');
readln(t2.hora);
write('minuto: ');
readln(t2.min);
write('segundo: ');
readln(t2.seg);
{calculo o número total de segundos}
t3.seg := t1.seg + t2.seg;
{calculo a soma dos minutos mais o número de segundos que virou minuto}
t3.min := t1.min + t2.min + t3.seg DIV 60;
{somo as horas mais o número de minutos que virou hora}
t3.hora := t1.hora + t2.hora + t3.min DIV 60;
{como seg não pode ser >60, guardo a parte menor, pois o resto
transformei em min}
t3.seg := t3.seg MOD 60;
{como min não pode ser >60, guardo a parte menor, pois o resto
transformei em hora}
t3.min := t3.min MOD 60;
{escrevo o resultado}
writeln(t3.hora,':',t3.min,':',t3.seg)
|
Agora, e se quisermos fazer uma função que retorne a soma? Como definimos um tipo com o RECORD, podemos fazer tal função:
PROGRAM P;
TYPE tempo = RECORD
hora : integer;
min : word;
seg : word
END;
VAR t1 : tempo;
t2 : tempo;
t3 : tempo;
FUNCTION soma(t1,t2:tempo) : tempo;
BEGIN
{calculo o número total de segundos}
soma.seg := t1.seg + t2.seg;
{calculo a soma dos minutos mais o número de segundos que virou minuto}
soma.min := t1.min + t2.min + soma.seg DIV 60;
{somo as horas mais o número de minutos que virou hora}
soma.hora := t1.hora + t2.hora + soma.min DIV 60;
{como seg não pode ser >60, guardo a parte menor, pois o resto
transformei em min}
soma.seg := soma.seg MOD 60;
{como min não pode ser >60, guardo a parte menor, pois o resto
transformei em hora}
soma.min := soma.min MOD 60
END;
BEGIN
write('hora: ');
readln(t1.hora);
write('minuto: ');
readln(t1.min);
write('segundo: ');
readln(t1.seg);
write('hora: ');
readln(t2.hora);
write('minuto: ');
readln(t2.min);
write('segundo: ');
readln(t2.seg);
t3 := soma(t1,t2);
{escrevo o resultado}
writeln(t3.hora,':',t3.min,':',t3.seg)
|
Vale lembrar que nem todos os compiladores aceitam tipos assim como retorno de uma função. Para esses compiladores, uma saída é definir um procedimento:
PROGRAM P;
TYPE tempo = RECORD
hora : integer;
min : word;
seg : word
END;
VAR t1 : tempo;
t2 : tempo;
t3 : tempo;
PROCEDURE soma(t1,t2:tempo; VAR t3:tempo);
BEGIN
{calculo o número total de segundos}
t3.seg := t1.seg + t2.seg;
{calculo a soma dos minutos mais o número de segundos que virou minuto}
t3.min := t1.min + t2.min + t3.seg DIV 60;
{somo as horas mais o número de minutos que virou hora}
t3.hora := t1.hora + t2.hora + t3.min DIV 60;
{como seg não pode ser >60, guardo a parte menor, pois o resto
transformei em min}
t3.seg := t3.seg MOD 60;
{como min não pode ser >60, guardo a parte menor, pois o resto
transformei em hora}
t3.min := t3.min MOD 60
END;
BEGIN
write('hora: ');
readln(t1.hora);
write('minuto: ');
readln(t1.min);
write('segundo: ');
readln(t1.seg);
write('hora: ');
readln(t2.hora);
write('minuto: ');
readln(t2.min);
write('segundo: ');
readln(t2.seg);
soma(t1,t2,t3);
{escrevo o resultado}
writeln(t3.hora,':',t3.min,':',t3.seg)
|
Números complexos: Sabemos que um número complexo possui sua parte real e imaginária. Assim, em (2+3i), 2 é a real e 3 a imaginária.
Como podemos, então, fazer procedimentos ou funções que executem as quatro operações em complexos? Antes de mais nada, vamos definir um tipo complexo:
TYPE complexo = RECORD
re : real;
im : real
END;
|
Agora, vejamos como são calculadas as 4 operações:
(a + bi) + (c + di) = (a + c) + (b + d)i (a + bi) - (c + di) = (a - c) + (b - d)i (a + bi) × (c + di) = (ac - db) + (bc + ad)i (a + bi) ÷ (c + di) = (ac + bd)/(c² + d²) + ((cb - ad)/(c² + d²))i |
Vejamos como ficam a soma e a multiplicação. A subtração e a divisão ficam como exercício para você.
PROGRAM P;
TYPE complexo = RECORD
re : real;
im : real
END;
VAR n1, n2, n3 : complexo;
FUNCTION soma(n1,n2:complexo) : complexo;
BEGIN
soma.re := n1.re + n2.re;
soma.im := n1.im + n2.im
END;
FUNCTION mult(n1,n2:complexo) : complexo;
BEGIN
mult.re := n1.re*n2.re - n1.im*n2.im;
mult.im := n1.im*n2.re + n1.re*n2.im
END;
BEGIN
{faço n1 := 2 + 3i}
n1.re := 2;
n1.im := 3;
{faço n2 := 4 - 2.3i}
n2.re := 4;
n2.im := 2.3;
n3 := soma(n1,n2);
writeln(n3.re,' + ',n3.im,'i'); {escreve 6 + 0.7i}
n3 := mult(n1,n2);
writeln(n3.re,' + ',n3.im,'i') {escreve 14.9 + 7.4i}
END.
|
Observações:
Comparação entre registros: No caso dos números complexos, como faço para verificar se um complexo é igual a outro? Infelizmente não há como fazer isso em Pascal:
TYPE complexo = RECORD
re : real;
im : real
END;
VAR t1,t2 : complexo;
BEGIN
{abasteço t1 com 2-3i}
t1.re := 2;
t1.im := -3;
{abasteço t2 com 4+2.3i}
t2.re := 4;
t2.im := 2.3;
IF t1 = t2 THEN
{faz algo}
END.
|
Como fazemos para testar registros então? Testamos campo a campo:
TYPE complexo = RECORD
re : real;
im : real
END;
VAR t1,t2 : complexo;
BEGIN
{abasteço t1 com 2-3i}
t1.re := 2;
t1.im := -3;
{abasteço t2 com 4+2.3i}
t2.re := 4;
t2.im := 2.3;
IF (t1.re = t2.re) AND (t1.im = t2.im) THEN
{faz algo}
END.
|
Pronto. Testado.
Registro dentro de registros: Vejamos agora, um exemplo de registro dentro de registro. Suponha que teremos que trabalhar com uma estrutura que deve conter uma data e um horário. O horário é algo assim:
TYPE horario = RECORD
hora : integer;
min : word;
seg : word
END;
|
Então, nossa estrutura seria algo assim:
TYPE horario = RECORD
hora : integer;
min : word;
seg : word
END;
TYPE data = RECORD
dia : 0..31;
mes : 1..12;
ano : integer
END;
TYPE tempo = RECORD
dia : data;
hora : horario
END;
|
Note que posso por nomes duplicados de campos (como "dia" e "hora"), desde que pertençam a registros diferentes.
Agora, como fazemos para armazenar uma data? E para ler?
TYPE horario = RECORD
hora : 0..23;
min : 0..60;
seg : 0..60
END;
TYPE data = RECORD
dia : 0..31;
mes : 1..12;
ano : integer
END;
TYPE tempo = RECORD
dia : data;
hora : horario
END;
VAR t : tempo;
BEGIN
{vou armazenar 12 de janeiro de 2002, 14h:05':30''}
t.dia.dia := 12;
t.dia.mes := 1;
t.dia.ano := 2002;
t.hora.hora := 14;
t.hora.min := 5;
t.hora.seg := 30;
{imprimo "12/1/2001 - 14:5:30"}
writeln(t.dia.dia,'/',t.dia.mes,'/',t.dia.ano,' - ',t.hora.hora,':',t.hora.min,':',t.hora.seg)
END.
|
Viu como funciona? Ao fazer t.dia estou acessando o campo "dia" do registro "t". Mas esse campo, por sua vez, é um registro também, então, não posso acessá-lo diretamente, tenho que acessar seus registros. Assim, para acessar o campo "mes" do registro correspondente ao campo "dia" do registro "t" faço "t.dia.mes".