UNIVERSIDAD TECNICA FEDERICO SANTA MARIA DEPARTAMENTO DE ELECTRONICA Programación en Pascal Capítulo 21. Registros. Records. 21. REGISTROS. Records . 21.1. Concepto Abstracto. Así como el arreglo es la estructura más usada por los programadores en un ambiente científico o de aplicaciones personales, el registro es la unidad básica de información en aplicaciones comerciales o que involucren cantidades masivas de datos. El registro es una estructura formada por un número fijo de componentes, denominados campos. A diferencia del arreglo, las componentes o campos pueden ser de tipos diferentes. Cada componente puede tomar un valor del conjunto definido por su tipo. Es decir, el conjunto de valores de un registro es el producto cartesiano de los conjuntos de sus componentes. Si nos imaginamos un eje, en el que se encuentran los valores que un campo puede adoptar; y un eje por cada campo, el valor de un registro puede visualizarse como una m-tupla en un espacio m-dimensional (con m campos en un registro). Puede observarse que una agrupación de valores de un registro, permite establecer una relación en ese espacio. 21.2 Usos de Registros. En un ambiente matemático la estructura registro permite representar números complejos y vectores; logrando de este modo tratar en forma computacional situaciones caracterizadas por estos objetos. En un ambiente comercial permite relacionar básicamente nombres con números, facilitando así la descripción de innumerables situaciones. Algunos ejemplos: nombres y apellidos con números de rol; una fecha con una descripción de una operación comercial, acompañada de un valor; un número de parte y la cantidad de ítems, o su valor; etc., etc. 21.3 Entidades y atributos. En aplicaciones de procesamiento masivo de datos, cuando se tiene una agrupación de valores de registros (normalmente en un archivo) por lo menos uno de los campos, es tal que sus valores no se encuentran repetidos en la agrupación. Es decir, un valor de ese campo, permite identificar unívocamente a un registro. Ese tipo de campo suele llamarse entidad, y también clave o llave (key); el resto de los campos se denominan atributos. Prof. Leopoldo Silva Bijit. 07-07-2003 261 UNIVERSIDAD TECNICA FEDERICO SANTA MARIA DEPARTAMENTO DE ELECTRONICA Programación en Pascal Capítulo 21. Registros. Records. 21.4 Registro Unitario. Desde tiempos anteriores a los computadores ya se guardaba información en tarjetas perforadas. En cada tarjeta se representa el valor de un registro. Es la estructura del registro la que permite asociar información con las perforaciones. La práctica de almacenar información en tarjetas hizo tradicional la dimensión de un registro en este ámbito; y suele ser de 80 bytes. El advenimiento de dispositivos magnéticos ha permitido ampliar el largo de los registros; pero los de largo 80 siguen siendo los más empleados, y se llaman registros unitarios. 21.5. Sintaxis. Nos interesa describir formalmente el conjunto de valores de tipo registro, y la forma de accesar e identificar las componentes. En Pascal pueden representarse las uniones discriminadas o registros con variantes. No se describirá esta posibilidad, por ser muy poco frecuente su uso en la práctica. Casi la totalidad de los registros que se emplean son con partes fijas. <declaración de registro fijo> ::= 'type' 'RECORD' <lista de campos > 'END' <lista de campos> ::= { ( { <nombre campo>* ',' } ':' <tipo> )* ';' } Nótese que pueden agruparse los campos que son de un mismo tipo, a través de una lista de nombres de campos separados por comas. Ejemplos: Type complejo = record real, imaginaria : real end; vector = record x, y, z : real end; Prof. Leopoldo Silva Bijit. 07-07-2003 262 UNIVERSIDAD TECNICA FEDERICO SANTA MARIA DEPARTAMENTO DE ELECTRONICA Programación en Pascal Capítulo 21. Registros. Records. lck = record corriente1, corriente2, corriente3: real end; cuenta = record codigo: integer; fecha: integer; nombre: array [1..25] of char; debe, haber: real end; fecha = record dia : 1..31; mes : 1..12; ano : 1900..3000 end; tiempo=record hora:1..24; min: 1..60; seg: 1..60 end; Observando las cuentas de los servicios de agua, luz, gas, teléfono; los volantes de saldos de cuentas corrientes; las listas de cursos; los kardexs de biblioteca; la guía de teléfonos y otras innumerables situaciones informáticas de la vida cotidiana, pueden encontrarse definiciones de registros. En todas ellas es la estructura del registro (es decir, los nombres y tipos de los campos) la que da sentido a las secuencias de dígitos y letras. Nótese que un campo puede ser estructurado, y que todos los nombres de campos deben ser diferentes. Type persona = record nombre,paterno,materno:packed array [1..15] of char; sexo: (M, F); fechanacimiento: record dia:1..31; mes:1..12; ano:0..99 end Prof. Leopoldo Silva Bijit. 07-07-2003 263 UNIVERSIDAD TECNICA FEDERICO SANTA MARIA DEPARTAMENTO DE ELECTRONICA Programación en Pascal Capítulo 21. Registros. Records. end; Se dice que el tipo persona es una estructura de registros anidados. Una forma gráfica de representar la estructura de un registro es la siguiente: cuenta: código fecha nombre debe haber Lo cual permite visualizar conceptualmente la estructura. 21.6 Construcción y Selección. Es necesario especificar cómo puede accesarse a una componente de los registros; y también cómo puede dársele valores, a dichas componentes. a) Actualización total o copia. Si se declaran: var x,y: cuenta; Y si el valor de y está definido, puede copiarse este valor en x, mediante: x := y; { copia} b) Sintaxis para la identificación, o seleción, de una componente: <componente de registro> ::= <variable de tipo registro> { '.' <nombre campo>*} La variable debe ser de tipo registro. La iteración permite accesar las componentes de un campo que a su vez es un registro. c) Actualización selectiva. Pueden escribirse, las siguientes actualizaciones selectivas: x.codigo := 10; Prof. Leopoldo Silva Bijit. 07-07-2003 264 UNIVERSIDAD TECNICA FEDERICO SANTA MARIA DEPARTAMENTO DE ELECTRONICA Programación en Pascal Capítulo 21. Registros. Records. x.nombre[5] := 'm'; x.debe := 10.2; y.codigo: = x.codigo; Se denomina selectiva, pues puede cambiarse el valor de una componente sin alterar el resto. Los registros se implementan en memoria primaria, y por esto se dice que son de rápido acceso. Además el espacio asignado a una variable de este tipo queda determinado en el momento de la compilación; por esto se dice que es una estructura estática. 21.7 Procesamiento de Registros. La identificación de una componente de un registro puede ser materia tediosa (a veces, difícil de escribir y leer, en el texto del programa) si los nombres de los registros y sus componentes son largos. Para mejorar la legibilidad, puede emplearse la instrucción with (con en español); que define un ámbito en el cual los campos de un registro pueden ser referenciados por su nombre solamente. Es decir, sin estar precedidos por el identificador del registro seguido de un punto. Ejemplo: Uso de with. El segmento asigna un valor a la variable f. var f: fecha; ... with f do begin dia:=29; mes:=6; ano:=1985 end; ... La sintaxis de esta instrucción es: <instrucción with> ::= 'WITH' { <variable>* ',' } 'DO' <instrucción> Prof. Leopoldo Silva Bijit. 07-07-2003 265 UNIVERSIDAD TECNICA FEDERICO SANTA MARIA DEPARTAMENTO DE ELECTRONICA Programación en Pascal Capítulo 21. Registros. Records. La variable debe ser de tipo registro; y la instrucción se dice que es calificada. La lista de variables no puede contener variables que sean modificadas por la instrucción calificada. Esta instrucción permite generar código más eficiente para la manipulación de componentes dentro del ámbito. Y al programador le permite redactar frases con menor redundancia. La instrucción with está especialmente diseñada para manipular registros; así como al instrucción for es útil en la manipulación de arreglos. Así como en el for la variable de control y las cotas no pueden ser modificadas en el bloque de repetición, tampoco se permite asignar valores a las variables de la lista del with, dentro del bloque calificado. Esto es particularmente importante cuando alguna variable de la lista contiene una componente de arreglo; ya que sólo será preciso evaluar una vez la expresión del índice. Ejemplo: with a[i] do {a[i] es de tipo registro} begin .. i:=i+1; {error} .. end; Si bien un registro puede parecer una generalización del arreglo, ya que relaja la restricción de componentes de igual tipo; en otro aspecto es menos general. Ya que para accesar a una componente debe emplearse un identificador de campo fijo; mientras que en un arreglo el mecanismo de selección, del índice, puede ser una expresión. 21.8. Manipulación de registros. Además de los mecanismos de construcción (total o selectiva) y selección (acceso a componente) y de procesamiento calificado (with), es preciso desarrollar procedimientos especiales para la lectura y escritura de valores de tipo registro; ya que las instrucciones read y write no manipulan variables ni expresiones de tipo registro. a) Relación de Orden. En caso de ser necesario, puede definirse una relación de orden. Asumamos: var x,y : record c1,c2 : integer end; Entonces: x<=y; Prof. Leopoldo Silva Bijit. 07-07-2003 266 UNIVERSIDAD TECNICA FEDERICO SANTA MARIA DEPARTAMENTO DE ELECTRONICA Programación en Pascal Capítulo 21. Registros. Records. puede implementarse verificando que: (x.c1<y.c1) OR (x.c1=y.c1) AND ((x.c2<y.c2) OR (x.c2=y.c2)) Nótese que si las primeras componentes son iguales, se efectúa la comparación de las segundas. Esta operación puede ser compleja en caso de existir un número elevado de campos. Ejemplo: --------------------| 10 | 80 | < | 11 | 79 | {valor true} --------------------También pueden definirse operaciones aritméticas especiales. Por ejemplo, pueden describirse procedimientos para implementar el álgebra de números complejos y de vectores. También pueden sumarse dos valores de tipo tiempo, empleando aritmética modular; la estructura de tiempo se describe según: tiempo: hora minutos segundos 21.9. Ejemplos de registros. Tema: Representación de strings de caracteres de largo variable. Antes se vió una solución en términos de arreglos. A continuación se verá una alternativa de diseño, empleando registros. La metodología a emplear será definir una estructura de datos y luego desarrollar procedimientos especiales que la manipulen. a) Estructura. El registro permite agrupar el largo del string y la secuencia de caracteres en un solo concepto. const lmax = 80; type string = record linea:array [1..lmax] of char; largo:0..lmax end; Prof. Leopoldo Silva Bijit. 07-07-2003 267 UNIVERSIDAD TECNICA FEDERICO SANTA MARIA DEPARTAMENTO DE ELECTRONICA Programación en Pascal Capítulo 21. Registros. Records. var c1, c2:string; b) Asignación. La secuencia: c1.linea[1]:='m'; c1.linea[2]:='a'; c1.largo:=2; Permite representar el string 'ma', en la estructura dada. Lo anterior es equivalente a: with c1 do begin linea[1]:='m'; linea[2]:='a'; largo:=2 end; c) Concatenación. El procedimiento concat, concatena dos strings, formando una tercera como resultado. procedure concat(s1,s2:string; var s3:string); var l1, l2, l3, i: integer; begin l1:=s1.largo; l2:=s2.largo; l3:=l1+l2; if l3>lmax then writeln('error à se excede el largo máximo'} else begin s3.linea:=s1.linea; for i:=l1+1 to l3 do s3.linea[i]:=s2.linea[i-l1]; s3.largo:=l3 end end; {concat} Observaciones: i) Una variante es truncar el máximo largo, se logra con: if l3>lmax then l3:=lmax; Prof. Leopoldo Silva Bijit. 07-07-2003 268 UNIVERSIDAD TECNICA FEDERICO SANTA MARIA DEPARTAMENTO DE ELECTRONICA Programación en Pascal Capítulo 21. Registros. Records. ii) Como no se efectúan asignaciones a s1 y s2, podrían haberse declarado parámetros variables (sólo de entrada); lo cual acelera la ejecución de concat. d) Prueba de igualdad. La siguiente función determina si dos strings son iguales. function tstigual(var s1,s2:string):boolean; var i,l:integer; igualdad: boolean; begin l:=s1.largo; if s2.largo<>l then tstigual:=false else begin i:=1;igualdad:=true; while (i<=l) and (igualdad) do if s1.linea[i]=s2.linea[i] then i:=i+1 else igualdad:=false; tstigual:=igualdad end end; {tstigual} d) Prueba de inclusión. Reconocimiento de patrones. La función pos retorna la posición de la primera ocurrencia de s2 en s1, si es que s2 está contenida en s1. Si lo anterior no ocurre, retorna valor cero. function pos(s1,s2:string):integer; var i,j,l1,l2:integer; estaba, seacabo:boolean; begin l1:=s1.largo; l2:=s2.largo; i:=0; estaba:=false; while (i+l2<=l1) and (not estaba) do begin seacabo:=false; j:=1; while (j<=l2) and (not seacabo) do Prof. Leopoldo Silva Bijit. 07-07-2003 269 UNIVERSIDAD TECNICA FEDERICO SANTA MARIA DEPARTAMENTO DE ELECTRONICA Programación en Pascal Capítulo 21. Registros. Records. if s1.linea[i+j]=s2.linea[j] then j:=j+1 else seacabo:=true; if j>l2 then estaba:=true else i:=i+1 end; if estaba then pos:=i+1 else pos:=0 end; {pos} Observaciones. La variable i se emplea para apuntar al inicio de la zona de revisión en s1; j referencia posiciones sucesivas en s2. La variable booleana seacabo permite detener una revisión si se encuentra tempranamente una diferencia. La variable estaba, permite detener la repetición de la búsqueda, comenzando en posiciones cada vez más alejadas del margen izquierdo, a la primera ocurrencia de s2 dentro de s1. La sintonización de un patrón (pattern matching) es un caso particular del problema de búsqueda. Los ejemplos anteriores ilustran una técnica general de programación; consistente en asociar a la estructura de datos empleada una serie de funciones y procedimientos especiales. Lo cual establece un ambiente adecuado para la elaboración de programas complejos. Prof. Leopoldo Silva Bijit. 07-07-2003 270