Está en la página 1de 9

Programación I – Capítulo VIII – Tipo de datos estructurados.

Tipos de datos Estructurados


Producto cartesiano
Una empresa de software que se dedica a la programación de juegos, está
interesada en lanzar una línea de juegos de cartas. Para ello se plantea el
problema de como representar un mazo de cartas, y más concretamente, como
representar una sola carta.

Para determinar el tipo de una carta se debe decidir qué características de la


misma se desean conocer. Dentro de las posibles características de una carta,
se deben elegir aquellas que son relevantes para el caso. Es decir, se deben
abstraer los datos que importan de la carta, desechando aquellos que son
irrelevantes.

A los efectos de lo que busca la empresa, se concluye que los datos relevantes
de una carta son el palo y el valor de la misma, mientras que el resto de las
características (dimensiones, color, etc.) son ignoradas.

Como una primera aproximación, se plantea representar a una carta mediante


una variable de un tipo predefinido. De este modo se puede representar el
valor (int) de la carta ó el palo (enum) de la misma, pero no hay forma de
representar ambos datos al mismo tiempo.

Otra alternativa es representar a la carta mediante 2 variables, una para


representar el valor y otra para representar el palo de la misma:

typedef enum {bastos,copas,espadas,oros} tipo_palo;


tipo_palo Palo;
int Valor;

De este modo queda definida una carta, sin embargo, no queda claro el hecho
de que ambas variables forman un único objeto. Dichas variables deberían
manejarse como si fuesen una sola, deberían estar relacionadas de alguna
forma.

Los lenguajes de programación proveen herramientas para solucionar este


problema. Dichas herramientas consisten en constructores de tipos que
permiten definir nuevos tipos de datos.
Cuando un objeto tiene una cantidad fija de características relevantes, no
necesariamente del mismo tipo, es posible definir un nuevo tipo, es decir, una
estructura para representarlo. De este modo, pueden generarse instancias o
variables del tipo definido.

Material de uso exclusivo para el curso Programación I dictado por INET 1


Programación I – Capítulo VIII – Tipo de datos estructurados.

En C: El Constructor de Tipos struct


El constructor de estructuras en C se llama struct. La introducción de un nuevo
tipo generado por este constructor se realiza según la siguiente sintaxis:

Definición de estructura
typedef struct {
T1 C1;
T 2 C2;
.........
.........
Tn Cn;
} NuevoTipo;

Donde:

C1, C2, …., Cn son los identificadores de cada componente.


T1, T2, …., Tn son los tipos correspondientes a cada componente,

y NuevoTipo es el nombre del tipo de de dato definido.

Por lo tanto, se puede definir una estructura para representar una carta, de la
siguiente manera:

typedef enum {oros, copas, espadas, bastos} tipo_palo;

typedef struct {
int valor;
tipo_palo palo;
} Carta;

Observación:
Se dice que un objeto tiene la estructura de un producto cartesiano, si de la
abstracción resulta que tiene una cantidad fija de características relevantes no
necesariamente del mismo tipo.

Todo objeto con esta estructura puede ser representado, en los lenguajes de
programación, por un tipo de datos generado por el constructor de tipos struct
(o similar).

Material de uso exclusivo para el curso Programación I dictado por INET 2


Programación I – Capítulo VIII – Tipo de datos estructurados.

Conjunto de Operaciones
Las operaciones predefinidas para un elemento de un tipo struct, son las que
se dan a continuación:

Asignación
Se realiza de la misma forma que el resto de las asignaciones:

identificador_variable = expresion_struct

Comparación
Esta operación no está disponible en el lenguaje y cuando se necesite deberá
ser implementada por el usuario.

Selección de una Componente


La selección de una componente de un objeto de un tipo struct se realiza a
través del operador punto ( . ), según la siguiente sintaxis:

NombreVariable . NombreDeLaComponente

Y el resultado es considerado como una variable del tipo de la componente


seleccionada.

Ejemplo:

Material de uso exclusivo para el curso Programación I dictado por INET 3


Programación I – Capítulo VIII – Tipo de datos estructurados.

Array con Tope


Una empresa necesita registrar cierta información de sus empleados a fin de
automatizar la liquidación mensual de haberes. Dicha información consiste en
el nombre, sueldo base y la antigüedad. Los empleados pueden variar de un
mes a otro, pero es política de la empresa no superar la cantidad de veinte
trabajadores.

Evidentemente, el arreglo es la estructura de datos que permite agrupar como


un solo objeto, una colección de valores del mismo tipo. Como el tipo del
elemento de un tipo arreglo de C puede ser cualquier tipo, es posible
implementar los conjuntos de valores no ordinales como arreglos. Otra ventaja
que tiene esta solución es que el operador de selección de los tipos arreglo,
permite acceder directamente a cualquier elemento del conjunto.

Por lo tanto una primer solución al problema sería:

const int CantEmp = 20;

typedef struct {
string nombre;
float sueldo_base;
int antiguedad;
} empleado;

typedef empleado Empresa[CantEmp];

A pesar de que el sistema se implementó con el programa anterior, es una


mala solución ya que no modela adecuadamente la realidad de la empresa,
pues el tipo de datos definido para implementarla impone que en todo momento
la cantidad de empleados sea exactamente veinte, cuando en realidad en el
análisis se estableció que esta cantidad es variable, siendo veinte una cota
superior.

Si la cantidad de empleados es menor, el algoritmo procesa elementos del


arreglo que no tienen información válida, datos de empleados que ya no están
en la empresa o simplemente son elementos del arreglo no inicializados.

Una posibilidad es llevar el registro de la cantidad de empleados que hay en


cada momento, actualizando este dato y reordenando el arreglo cada vez que
se produce un alta o una baja. De esta forma, sólo se procesan los elementos
del arreglo donde hay empleados válidos, esto es, los que corresponden a los
índices desde el 0 hasta el valor de la cantidad de empleados menos uno.
Además, se puede representar la empresa sin empleados (el conjunto vacío): si
la cantidad es cero, todos los elementos del arreglo contienen valores no
válidos.
Por la relevancia que adquiere este valor, junto al arreglo, esta pareja se
estructura como un solo objeto en un producto cartesiano, formando una
estructura llamada array con tope, cuya sintaxis es:

Material de uso exclusivo para el curso Programación I dictado por INET 4


Programación I – Capítulo VIII – Tipo de datos estructurados.

Definición de Array con tope


typedef struct {
Tipo_base Array[n];
int tope;
} Array_con_tope;

Donde Array es una colección de n elementos de tipo Tipo_base, tope es un


entero que indica la cantidad de elementos inicializados del Array.

Podemos definir a la empresa de la siguiente forma:

• En el campo “empleados” se almacenan los distintos valores del


conjunto, los cuales no pueden superar, en cantidad, la cardinalidad
del tipo índice del array.

• El campo tope puede verse desde dos puntos de vista:

o como la cantidad de elementos que tiene el conjunto, siendo estos


los ubicados en las posiciones 0,1, 2, ...., tope-1.

o como un índice o puntero al siguiente elemento del array luego del


último elemento con un valor válido, considerando vacías las
posiciones del array desde el tope al final.

Advertencia:
Es responsabilidad del programador usar la estructura adecuadamente,
asegurándose de no acceder a elementos del arreglo que estén más allá del
tope, a menos que se pretenda agregar un nuevo elemento.

Unión Discriminada

Los empleados de la empresa mencionada en el punto anterior, se dividen


ahora en funcionarios y jornaleros. La información que se maneja de los
mismos, a los efectos de la liquidación mensual de haberes, depende de esta

Material de uso exclusivo para el curso Programación I dictado por INET 5


Programación I – Capítulo VIII – Tipo de datos estructurados.

clasificación. De los funcionarios interesa su nombre, sueldo base y antigüedad


mientras que de los jornaleros interesa el nombre, sueldo base y la cantidad de
horas trabajadas en el mes.

Personal puede ser

Funcionario: Características relevantes


nombre: string
sueldo base: real
antigüedad: entero

Jornalero: Características relevantes


nombre: string
sueldo base: real
horas trab.: real

Se puede definir un tipo para cada una de las clases de empleado:

Luego se puede definir el tipo empleado de la siguiente manera:

Lo que obligaría que cada empleado tuviera dos componentes, un funcionario y


un jornalero; claramente esta situación no es deseable ya que para cada
empleado, y dependiendo de la categoría a la que pertenece, la componente de
funcionario o la de jornalero quedaría vacía.
Seria imprescindible para este tipo de casos, contar con un constructor de tipos
que permita, a partir de una serie de componentes, disponer únicamente de una
de ellas a la vez, a diferencia del constructor de tipos struct. Un objeto con esta
estructura puede ser representado mediante una unión discriminada.

Material de uso exclusivo para el curso Programación I dictado por INET 6


Programación I – Capítulo VIII – Tipo de datos estructurados.

En C: El Constructor de Tipos union


C no provee un constructor de tipos Unión Discriminada, pero el mismo puede
implementarse en base al constructor unión. La introducción de un nuevo tipo
generado por este constructor se realiza según la siguiente sintaxis:

Definición de un tipo unión


union{
T1 c1;
T2 c2;
.......
Tn cn;
} [ etiqueta ] ;

donde:
c1,c1, …., cn
son nombres que se le dan a cada componente las cuales corresponden
a los tipos T1,T2, ...,Tn , lo cual permite referenciar fácilmente una de
ellas.

etiqueta es un nombre para la estructura.

Una variable de un tipo unión, en un momento determinado, almacena una sola


de las posibles componentes. Cualquiera de los tipos Ti puede ser asignado a
una variable y después emplear a esta en expresiones, mientras que su uso
sea consistente. Es responsabilidad del programador controlar el tipo
almacenado.

Primera Solución al Problema:


Una primera solución al problema, en C, podría plantearse como sigue:

Material de uso exclusivo para el curso Programación I dictado por INET 7


Programación I – Capítulo VIII – Tipo de datos estructurados.

Implementación de la Unión Discriminada en C


Para un correcto empleo, desde el punto de vista conceptual, del tipo unión
discriminada, es necesario manejar una componente que permita conocer el tipo
del valor que está almacenado en la unión en ese momento. En el ejemplo que
se viene manejando, el tipo empleado debería contar con una componente para
la categoría con el fin de saber si el valor almacenado corresponde al tipo
funcionario o jornalero. Esta componente recibe el nombre de discriminante.

Una mejor solución al problema, en C, podría plantearse como sigue:

Si e es una variable de tipo empleado, según el valor de e.discriminante se


accederá a e.datos.f o e.datos.j.

Observación:
Generalmente, al realizar uniones discriminadas, los tipos intervinientes en la
construcción del nuevo tipo, tienen alguna componente en común (en el caso
anterior, el nombre y el sueldo base). Podría aprovecharse este hecho para
hacer una definición algo diferente:

Material de uso exclusivo para el curso Programación I dictado por INET 8


Programación I – Capítulo VIII – Tipo de datos estructurados.

Observación:
En la unión se reserva un espacio de memoria del tamaño de la componente
más grande, suficiente para poder almacenar cualquiera de las componentes, en
lugar de reservar un espacio independiente para cada una de las componentes.

Esta situación se puede ver más claramente en la siguiente figura:

Si se reserva espacio para el campo de mayor tamaño de la unión (float), ambos


campos pueden representarse en el mismo espacio de memoria (4 bytes). En
cambio, si se reservan espacios independientes de memoria para cada campo,
éstos ocuparán 6 bytes, es decir, 2 bytes para la antigüedad (int) y 4 bytes para
la cantidad de horas trabajadas (float).

Conjunto de Operaciones
Las operaciones sobre uno de estos tipos son:

Asignación
Se realiza según la sintaxis tradicional.

Comparación
Dos valores e1 y e2 de un tipo unión discriminada son iguales si pertenecen al
mismo tipo y tienen el mismo valor según el tipo al que pertenecen.
En general, en los lenguajes de programación esta operación no está
predefinida, y su definición queda a cargo del programador.

Convertir el Valor al Tipo Original


Esta operación se realiza seleccionando la componente correspondiente al tipo
al que pertenece el valor almacenado. Dicha selección se realiza median te el
operador punto (.), y el resultado es considerado como una variable del tipo de
la componente seleccionada.

Material de uso exclusivo para el curso Programación I dictado por INET 9

También podría gustarte