viernes, 28 de marzo de 2008

Estructura de dato: Registro. Tratamiento de cadenas


Abajo

CLASE 6: Estructura de dato: Registro. Tratamiento de cadenas.

Estructuras de datos

El tipo registro

El tipo registro es una estructura de datos cuyas componentes se denominan campos, los cuales entre ellos pueden ser de diferentes tipos, por lo tanto, el tipo registro es una estructura heterogénea. Podemos referirnos a todo el conjunto de datos bajo un solo nombre, esto es, la variable de tipo registro, además podemos referirnos a solo una componente, usando la siguiente notación: NombreRegistro.NombreCampo, en donde: NombreRegistro es una variable de tipo registro y NombreCampo es una de las componentes del registro. El tipo registro es una estructura de datos estática, debido a que el compilador asignará una cantidad de byte en la memoria, del tamaño de la longitud del registro, esto es la sumatoria de las longitudes de cada componente. Para definir un tipo registro se utiliza la palabra reservada record. Los campos del registro se definen dentro de su ámbito, en la sección type, por lo cual, los nombres de los campos serán de uso global, es decir, en cualquier lugar del programa, siempre nos referiremos a un campo con los mismos nombres definidos en la sección type. No así con respecto al nombre del registro que podremos dar distintos nombres según en el lugar del programa en que nos encontremos.

La asignación entre registros es válida siempre y cuando sean del mismo tipo, si regA y regB son de tipo Reg, con campos cmp1, cmp2, ..., cmpn, entonces:

regB <-- regA, es válida, y es lo mismo que hacer: regB.cmp1 <-- regA.cmp1; regB.cmp2 <-- regA.cmp2; ...; regB.cmpn <-- regA.cmpn.

Cada campo de un tipo registro podrá ser de tipo simple o bien de tipo estructurado como es el tipo registro, en estos casos, los subcampos se definen bajo otro apartado record y la notación será, NomReg.NomCmp.NomSubCmp. El caso típico es un campo fecha y los subcampos dia, mes y año.

Ejemplo: rAlumno.FecNac.aa, en donde: rAlumno es una variable de tipo RegAlu, FecNac es un campo de tipo Fecha y aa es un subcampo de tipo word. A continuación se presenta una vista gráfica de lo que podría ser un registro de una transacción o novedad de una venta de un vendedor:


Tamaño del registro = 16 bytes.

Pasaje de parámetros de tipo registro

Las variables de tipo registro pueden ser pasadas como parámetros a los módulos por valor o por referencia, tanto el registro completo como una de sus componentes simples o estructuradas. A continuación se lista un programa que muestra el uso del tipo registro:

Program EjemploRegistro;
Uses
Crt;

Type
Str20 = string[20];
Fecha = record
aa : word;
mm,
dd : byte
end;
RegAlu = record
NroLeg : longint;
ApeNom,
Domic,
Local : str20;
FecNac : Fecha;
EstCiv : char;
Trabaja : boolean;
NroDoc : longint
end;

procedure ProcAlum(var rAlu : RegAlu);
begin
writeln(rAlu.NroLeg);
writeln(‘Ing. Apellido y nombre: ‘);
readln(rAlu.ApeNom)
end;

procedure EmiteAlum(ApeN : str20);
begin
writeln(‘Apellido y Nombre: ‘,ApeN);
delay(2000)
end;

var
rAlumno,
rAlumno2 : RegAlu;

begin
rAlumno.NroLeg := 123456;
writeln(rAlumno.NroLeg);
rAlumno.FecNac.mm := 5;
rAlumno2 := rAlumno;
if rAlumno.NroLeg = 123456 then
ProcAlum(rAlumno) {Pasa todo el registro}
Else
EmiteAlum(rAlumno.ApeNom) {Pasa solo el campo ApeNom}
end.

Tratamiento de cadenas de caracteres

Una cadena es una disposición o conjunto de caracteres o símbolos tomados de un alfabeto, que en el caso de las PC, ese alfabeto es el ASCII. Una computadora debe ser capaz no solo de procesar valores numéricos, sino también de procesar datos no numéricos, es en esta categoría en donde entran las cadenas.
El tratamiento de cadenas es bastante habitual, más allá de lo que podemos creer, p.e. al escribir un programa fuente en algún lenguaje de computadora, estamos utilizando cadenas, que posteriormente al compilarlo tomará esas cadenas para analizar si son palabras válidas del lenguaje empleado. Por otro lado, un programa debe poder procesar frases o mensajes, como ser:
‘Ingrese su nombre’, ‘¿Cómo está Ud. ‘ + Nom + ‘?’, entre otras situaciones que se verán a continuación.
La cadena vacía es la cadena con longitud lógica = 0, y se la representa con dos apóstrofos contiguos, p.e.: cad1 <-- ‘’ Un objeto variable se lo declara de tipo cadena por medio de la palabra reservada string que presenta dos formatos de uso: string o string[n], en el primer caso declara una variable con una longitud física de 256 bytes lo que permite almacenar hasta 255 caracteres y en el segundo caso declara una variable con una longitud física de n + 1 bytes lo que permite almacenar hasta n caracteres. El byte adicional está reservado para alamacenar el atributo de la longitud lógica de la cadena. Para el tratamiento de cadenas existen tres operaciones básicas, a saber.
  • Longitud de la cadena
  • Concatenación de cadenas
  • Sub-cadenas
Longitud de la cadena

Toda cadena tiene una longitud finita de caracteres, determinar cuál es la cantidad de caracteres que posee una cadena, es conocer su longitud lógica, por lo tanto la entrada es una cadena y su salida es un valor entero, que indica la cantidad de caracteres que contiene en un momento determinado del proceso, ese valor estará entre cero y el máximo permitido en su declaración. La longitud lógica de una cadena es dinámica debido a que podrá cambiar en tiempo de ejecución. Por ejemplo, si cad1 <-- ‘super’, para determinar la longitud lógica hacemos longitud(cad1), que responderá con un valor entero de 5.
Concatenación de cadenas

Es la operación que permite unir dos o más cadenas en una sola. La nueva cadena contendrá cada una de las cadenas en el orden en que han sido unidas y su longitud lógica será igual a la suma de c/u. de las longitudes lógicas de esas cadenas. Así p.e. si cad1 <-- ‘super’ y cad2 <-- ‘man’, cad <-- concatenar(cad1,cad2) = cad1 + cad2 = ‘superman’ cuya longitud lógica es de 8. La operación de concatenación generalmente, no es conmutativa, vale decir que, cad1 + cad2 <> cad2 + cad1, en cambio, si realizamos la siguiente operación cad1 + ‘’ = ‘’ + cad1, notamos que genera la misma cadena resultado, o este otro ejemplo: ‘aa’ + ‘aaaaa’ = ‘aaaaa’ + ‘aa’, produce la misma cadena resultado.
Si el resultado de concatenar cadenas resulta una cadena con longitud mayor a lo esperado, en estos casos se trunca o corta la cadena hasta la longitud máxima aceptada, p.e. si cad está definida de tipo str7, realizar cad <-- ‘superman’, truncará en ‘superma’.
Sub-cadena

Es la operación que permite obtener una parte de una cadena, sin modificar la cadena original, en realidad se hace una copia. Así p.e., podríamos desarmar la operación de la concatenación. Para ello debemos saber que esta operación requerirá de las siguientes entradas: la cadena, el punto de inicio y la cantidad de caracteres a obtener, contando a partir del punto de inicio y obtendremos como resultado una cadena. Si queremos desarmar el contenido de cad del ejemplo anterior en sus dos partes, procederíamos de la siguiente manera:

cadUno <-- subCadena(cad,1,longitud(cad1)) y
cadDos <-- subCadena(cad,longitud(cad1) + 1,longitud(cad2))

Nota: Las palabras longitud, concatenar y subCadena han sido seleccionadas del lenguaje castellano a efectos de dar claridad a los conceptos indicados anteriormente.

Una cadena puede ser tratada de dos formas:
  • Completa, p.e.: cad
  • Individual –por sus componentes, es decir, por sus caracteres o símbolos-, siendo la notación cad[i], en donde el subíndice indica la componente i, cuyo valor debe estar en el intervalo [0; n], si i = 0 entonces hace referencia a la longitud lógica de la cadena.
Para las operaciones de cadena tratadas en forma completa cualquier cambio que se produzca en la longitud lógica es modificada automáticamente, en cambio, cuando es tratada en forma individual y se produzca una modificación en su longitud es necesario que lo realice el programador, forzando el cambio en la componente cero con el nuevo valor de longitud lógica.
Representación gráfica de una variable cadena en memoria, dado el siguiente tipo de dato y la declaración de variable de ese tipo de dato:

type
str20 = string[20];

var
cad : str20;
longitud física –estática, no cambia, definida en tiempo de compilación-

byte de longitud lógica -dinámica, su valor puede cambiar en tiempo de ejecución-.

Si bien el máximo valor es 255, en realidad no debe ser mayor al valor de la longitud física previamente definido, y no menor que cero, es decir, chr(0) <= cad[0] <= chr(n). El valor que se establezca no ha de ser numérico, sino, ha de ser de tipo caracter. A continuación se presentan distintos valores que contendrá la variable cad definida de tipo cadena de 20 -string[20]-.

Los 3 caracteres de signo de pregunta simbolizan el caracter que se encuentre en esas componentes.

Una cadena puede ser comparada con otra, utilizando los distintos operadores de relación (>, <, =, <>, >=, <=). Para que una cadena sea igual a otra se deben comparar todos sus caracteres correspondientes, esta tarea la realiza directamente el lenguaje Turbo Pascal. Al igual que los números reales una cadena es no ordinal. Pero, ¿será ordinal si la tratamos individualmente?. Si asignamos a una variable destino una cantidad de símbolos mayor al que puede contener, los caracteres que sobrepasen el límite superior se truncarán, es decir, se pierden todos aquellos caracteres que sobrepasen la cantidad máxima soportada por la variable destino, esto vale cuando la tratamos en forma completa, no así cuando la tratamos en forma individual y si sobrepasamos el límite superior, entonces en estos casos estaremos invadiendo una posición de memoria desconocida, produciendo efectos catastróficos, los cuales podrían llegar a ser, que determinadas variables hayan modificado su valor, aparecer caracteres imprevistos en la pantalla, colgarse el programa, entre otros.


Funciones y Procedimientos para el tratamiento de cadenas de caracteres

Chr(x): Retorna el caracter correspondiente al código ASCII x enviado.
Ej. car <--char(65), asigna el caracter ‘A’.
Ord(car): Retorna el código ASCII correspondiente al caracter enviado.
Ej. x <-- ord(‘A’), asigna el valor 65. Es la función inversa de chr(x). Otra forma de obtener la longitud lógica de una cadena es aplicando esta función de la siguiente manera, x <-- ord(cad[0]). Asigna a x un valor entre 0 y 255, el que se encuentre en esa posición.
UpCase(car): Retorna el carácter convertido a mayúscula, si car es alfabético minúscula, sino el mismo caracter. car <-- UpCase(‘a’), asigna ‘A’. car <-- UpCase(‘B’), asigna ‘B’. car <-- upcase(‘+’), asigna ‘+’.
Length(cad): Retorna la longitud lógica de la cadena cad enviada. El valor retornado estará entre 0 y 255 como máximo. Length(cad) = ord(cad[0].
Pos(subCad,cad): Retorna cero si la subcadena subCad no se encontró en la cadena cad, sino retorna un valor > 0 indicando que en esa posición se encontro a partir de ahí la subcadena en la cadena.
Ej.: x <--pos(‘ma’,’mi mama me ama’), asigna 4 a x. x <-- (‘abc’,’xyzabrscbaqrbcmds’), asigna cero a x.

Copy(cad,i,x): Retorna una cadena armada a partir de la cadena cad desde la posición i, con x caracteres contando a partir de la posición i.
Ej.: cad1 ß copy(‘superman’,3,3), asigna ‘per’ a cad1.

Concat(cad1,cad2,...): Retorna una cadena, resultado de unir cada una de las cadenas enviadas en el orden dado. Otra forma de lograr el mismo propósito es utilizando el operador de concatenación ‘+’.
Ej.: cad <-- concat(‘super’,’man’). cad <-- ‘super’ + ‘man’.

SizeOf(objeto): Retorna un valor entero que indica el tamaño físico del objeto enviado que puede ser un tipo o una variable.
Ej.: x <-- sizeof(integer), asigna dos a x. x <-- sizeof(real), asigna 6 a x. x <-- sizeof(cad), asigna 21 a x si cad se definió como string[20]. x <-- sizeof(str20), asigna 21 a x si str20 se definió como string[20].

Succ(exprOrd): Retorna el sucesor de exprOrd que debe ser de tipo ordinal. Salvo el último elemento que no tiene sucesor, en tal caso sería error averiguarlo, todos los demás elementos tienen sucesor. El primer elemento de una lista tiene valor ordinal cero, salvo con los enteros negativos que tendrán valores ordinales negativos.
Ej.: x <-- succ(4), asigna 5 a x. X <-- succ(succ(10)), asigna 12 a x.

Pred(exprOrd): Retorna el predecesor de exprOrd que debe ser de tipo ordinal. Salvo el primer elemento que no tiene predecesor, en tal caso sería error averiguarlo, todos los demás elementos tienen predecesor. El primer elemento de una lista tiene valor ordinal cero, salvo con los enteros negativos que tendrán valores ordinales negativos.
Ej.: x <-- pred(4), asigna 3 a x. X <-- pred(pred(9)), asigna 7 a x. Car <-- pred(‘C’), asigna ‘B’ a car.

Delete(cad,i,x): Procedimiento que elimina de la cadena cad los caracteres desde la posición i una cantidad x de caracteres contando a partir de la posición i, actualiza la longitud lógica de cad.
Ej.: cad <-- ‘superman’. delete(cad,3,3), cad contiene suman y su longitud lógica es 5, se eliminaron los caracteres ‘p’, ‘e’ y ‘r’.

Insert(subCad,cad,i): Procedimiento que inserta la subcadena subCad en la cadena cad a partir de la posición i, actualiza la longitud lógica de cad.
Ej.: insert(‘per’,cad,3), ahora cad volverá a contener ‘superman’ y su longitud lógica volverá a ser de 8.

Str(x,cad): Procedimiento que convierte un número x a una cadena, el resultado queda en cad.
Ej.: str(725,cad), asigna a cad la cadena ‘725’ y su longitud lógica pasa a ser de 3. str(3825.425:0:2,cad), asigna a cad la cadena ‘3825.425’, en cambio str(3825.425,cad), asigna a cad la cadena ‘3.8254250’ que no es lo que se pretendería hacer.

Val(cad,x,cod): Procedimiento que convierte una cadena cad a un valor numérico, guardando el resultado en x, si la conversión tuvo éxito, en ese caso a cod se asigna cero. Puede ocurrir que no tenga éxito la conversión, en este otro caso se detiene la conversión, en x se asigna cero y en cod se asigna un valor > 0, indicando que en esa posición ocurrió un error, debido a que el caracter encontrado no pudo ser convertido a un dígito o signo + o – o el punto decimal.
Ej.: cad <-- ‘5318’. Val(cad,x,cod), asigna el valor 5318 a x, y a cod el valor 0, en cambio si cad <-- ‘3a92’. Val(cad,x,cod), asigna 0 a x, y a cod el valor 2, ya que, en la posición 2 se encontró un caracter que no pudo ser convertido. Funciones de tratamiento de cadenas creadas por el usuario

Al igual que con las funciones numéricas en que el usuario puede crear sus propias funciones, sucede lo mismo con las cadenas de caracteres. A continuación se presentan algunas funciones de cadenas.

Función que retorna el carácter enviado convertido a minúscula si es alfabético mayúscula, sino el mismo carácter.

Función que retorna invertida una palabra enviada:



Una posible aplicación de la función InvPal sería comprobar si una palabra es palíndromo, es decir, capicúa, p.e.: capicua <-- pal = InvPal(pal), habiendo declarado a capicua de tipo boolean, contendrá false si la palabra pal no es capicúa, sino será true. Pero, ¿podría ocurrir que al invertir una cadena, palabra de un lenguaje, la nueva cadena creada sea una palabra que pertenezca a ese mismo lenguaje?. p.e.: palreves <-- invpal(‘lámina’), obviando el tilde, asigna ‘animal’, o esta otra, palreves <-- invpal(‘roma’), asigna ‘amor’. Función que dado un caracter car y un número n, retorna el carácter car repetido n veces, es decir, retorna una cadena de longitud n, en donde cada componente es el caracter car.

También podría realizarse la siguiente función que retorna espacios en blanco:

Una posible aplicación de la función space o replicate podría ser rellenar una variable de cadena con espacios a derecha, a partir de la longitud lógica + 1 hasta el final, p.e.: cad <-- ‘Algoritmos’. cad <-- cad + space(pred(sizeof(cad)) – length(cad)).






Anterior: Procedimientos

Siguiente: Lenguaje Turbo Pascal




Arriba

No hay comentarios: