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".