ESTRUCTURAS Y UNIONES en C++

| 2013-04-23 | No hay comentarios »

Enumeración de tipos

Examinemos el archivo 40ENUM.CPP como un ejemplo del uso de tipos de variables enumeradas.


#include <iostream.h>

enum resultado {gana, pierde, ata, cancela};

main()

resultado result;{

enum resultado omit = cancela;

&nbsp;

for (result = gana;result <= cancela;result++) {

if (result == omit)

cout << "El juego ha sido cancelado\n";

else {

cout << "Se ha jugado ";

if (result == gana)

cout << "y nosotros ganamos!";

if (result == pierde)

cout << "y nosotros perdimos.";

cout << "\n";

}

}

}

En el programa ejemplo se usa la palabra enum en la línea 8, pero se la omite en la línea 7 para ilustrar que es optativo.

¿QUÉ ES UNA ESTRUCTURA?

Estructura es un tipo de dato definido por el usuario. Nosotros tenemos la capacidad de definir nuevos tipos de datos considerablemente más complejos que los tipos manejados hasta ahora. Una estructura  es una combinación de varios datos definidos previamente, incluyendo otras estructuras ya definidas. Una definición fácil de entender sería: “Es un grupo de datos afines en una forma fácil de usar para el programador o usuario del programa. La mejor forma de entender la estructura es viendo un ejemplo:

41STRUCT1.C


main()

{

&nbsp;

struct {

char initial;    /* inicial del 2o.nombre  */

int age;         /* edad                   */

int grade;       /* curso escolar          */

} boy,girl;

&nbsp;

boy.initial = 'R';

boy.age = 15;

boy.grade = 75;

&nbsp;

girl.age = boy.age - 1;  /* ella es un año menor    */

girl.grade = 82;

girl.initial = 'H';

&nbsp;

printf("%c tiene %d años y un grado escolar de %d\n",

girl.initial, girl.age, girl.grade);

&nbsp;

printf("%c tiene %d años y un grado escolar de %d\n",

boy.initial, boy.age, boy.grade);

}

El programa empieza con la definición de una estructura. La palabra clave «struct» es precedida por algunas variables simples entre llaves, las cuales son componentes de la estructura . Después de la llave de cierre encontramos dos variables listadas, de nombre «boy» y «girl». De acuerdo con la definición dada anteriormente, «boy» es ahora una variable compuesta de 3 elementos, «initial«, «age» y «grade«. Cada uno de los campos está asociado a «boy» y, cada uno puede almacenar una variable de su respectivo tipo. La variable «girl» es también una variable con 3 campos asociados con los mismos nombres que para «boy», pero son variables distintas. Hemos definido por tanto, 6 variables.

 

UNA VARIABLE COMPUESTA

Examinemos la variable «boy más detenidamente. Como hemos dicho antes, cada uno de los 3 elementos de «boy» es una variable simple, y puede utilizarse en cualquier programa C, tal como se usa una variable de ese tipo. Por ejemplo, «age» es una variable entera y, por tanto, puede servir en cualquier zona de programa que necesite una variable «int» en, por ejemplo, cálculos, contadores, operaciones de E/S, etc. El único problema que tenemos es en como definir el uso de la variable simple «age», la cual es parte componente de «boy». Usamos ambos nombres con un punto decimal entre ellos, con el nombre de la estructura en primer lugar. Entonces, el nombre completo y correcto de la variable de estructura «age» sería: “boy.age«. Esta construcción puede usarse en cualquier parte del programa, en la cual deseemos referirnos a la estructura «boy». Obviamente es del todo incorrecto utilizar un nombre sin el otro, o sea, mencionar sólo el nombre de la estructura, o la variable a secas. Estaremos hablando de expresiones vacías.

 

ASIGNANDO VALORES A LAS VARIABLES

De acuerdo con la definición anterior, podemos asignar valores a cada una de las 3 variables asociadas a «boy», y a cada uno de los 3 componentes de «girl». «boy.initial» es un valor tipo «char», porque fue asignado así a la estructura. Por tanto, contendrá un caracter: a «boy.initial» se le asigna el caracter «R» de acuerdo con su definición.. Al resto de componentes de la estructura se les asigna valores de su respectivo tipo. Finalmente, a los componentes de «girl» se les asigna valores distintos, en orden distinto, a fin de demostrar que el orden de asignación de valores a la estructura no afecta al funcionamiento de ésta.

 

COMO USAR LOS DATOS RESULTANTES

Ahora que ya hemos dado valores a las seis variables, podemos hacer lo que queramos con ellas. A fin de hacer este primer ejemplo lo más sencillo posible, sólo mostramos las variables por pantalla, para ver si contienen algo. Los «printf» no tienen nada especial. El nombre compuesto de cada variable es especificado, ya que es el único válido a la hora de referirse a ella.

Las estructuras constituyen un buen método para agrupar datos a fin de hacer más fácil la escritura y la comprensión del programa.

 

ESTRUCTURA DE ARRAYS

42STRUCT2.C


main()

{

struct {

char initial;

int age;

int grade;

} kids[12];

&nbsp;

int index;

&nbsp;

for (index = 0;index < 12;index++) {

kids[index].initial = 'A' + index;

kids[index].age = 16;

kids[index].grade = 84;

}

&nbsp;

kids[3].age = kids[5].age = 17;

kids[2].grade = kids[6].grade = 92;

kids[4].grade = 57;

&nbsp;

for (index = 0;index < 12;index++)

printf("%c tiene %d años y un grado escolar de %d\n",

kids[index].initial, kids[index].age,

kids[index].grade);

}

Contiene la misma definición de estructura que el anterior, excepto en que en este definimos un array de 12 variables denominadas «kids» con 3 campos. Este programa contiene, por tanto, 12 veces 3, o sea, 36 variables simples, cada una de las cuales puede almacenar un dato de acuerdo con su tipo. También definimos una variable simple denominada «index», para su uso en un bucle.

Para asignar un valor a cada componente, empleamos un bucle «for», y a cada paso del bucle se efectúa una asignación a cada uno de los 3 componentes. Un paso de bucle asigna todos los valores a un «kid». Esto no sería muy útil en una situación real, para asignar datos, pero el bucle podría leer de un fichero y almacenar esos valores en las variables adecuadas. Puede considerarse esto como el principio de una base de datos, ya que así es.

En las siguientes instrucciones del programa asignamos nuevos valores a algunos de los componentes, para mostrar el método utilizado para hacerlo.

Los últimos mandatos contienen un bucle «for» en el cual todos los valores generados aparecen por pantalla en un formato claro.

 

ESTRUCTURAS ANIDADAS Y CON NOMBRE

Las estructuras vistas hasta ahora eran muy simples, aunque útiles. Es posible definir estructuras conteniendo docenas y, a veces, cientos o miles de elementos. Sería una ventaja para el programador no definir todos los elementos en un solo paso, sino hacerlo de forma estructurada, en árbol. Esto será objeto del siguiente programa.

43NESTED.C


#include <string.h>

main()

{

struct person {

char name[25];

int age;

char status;        /* M = casado, S = soltero */

} ;

&nbsp;

struct alldat {

int grade;

struct person descrip;

char lunch[25];

} student[53];

&nbsp;

struct alldat teacher,sub;

teacher.grade = 94;

teacher.descrip.age = 34;

teacher.descrip.status = 'M';

strcpy(teacher.descrip.name,"Mary Smith");

strcpy(teacher.lunch,"Baloney sandwich");

&nbsp;

sub.descrip.age = 87;

sub.descrip.status = 'M';

strcpy(sub.descrip.name,"Old Lady Brown");

sub.grade = 73;

strcpy(sub.lunch,"Yogurt and toast");

&nbsp;

student[1].descrip.age = 15;

student[1].descrip.status = 'S';

strcpy(student[1].descrip.name,"Billy Boston");

strcpy(student[1].lunch,"Peanut Butter");

student[1].grade = 77;

&nbsp;

student[7].descrip.age = 14;

student[12].grade = 87;

}

La primera estructura contiene 3 elementos, pero no está seguida por ningún nombre de variable. No hemos definido, por tanto variables sólo para la estructura, pero le hemos dado nombre, «person«, al principio de la estructura. Este nombre puede ser utilizado para referirse a la estructura, pero no para ninguna variable de esta. Hemos creado un nuevo tipo de variable, que podemos manejar tan fácilmente como manejamos tipos «int», «char» o cualquier otro tipo existente en C. La única condición que conlleva es que este nuevo tipo debe ir siempre asociado a la palabra «struct».

 

La siguiente definición de estructura contiene 3 campos, con el campo central del tipo de la estructura anterior, es decir «person». Esta variable se llama «descript». Por tanto, la nueva estructura contiene 2 variables simples, «grade» y una cadena denominada «lunch[25]», y la estructura «descript». Ya que «descript» contiene 3 variables, la nueva estructura contiene realmente 5 variables. A esta estructura se le da otro nombre, «alldat» que además constituye un nuevo tipo de variable. Finalmente definimos un array de 53 variables cada una con la estructura definida por «alldat» y cada una de nombre «student». Hemos definido un total de 53 veces 5 variables, cada una de las cuales es capaz de almacenar un valor.

Ya que hemos creado un nuevo tipo de variable, usémoslo para definir 2 variables más. Las variables «teacher» y «sub» se definen en el siguiente mandato como variables de tipo «alldat», por lo cual cada variable contiene 5 campos que pueden almacenar datos.

 

En las 5 siguientes líneas de programa, asignaremos valores a cada uno de los campos de «teacher». El primer campo es «grade» y se expresa igual que las otras estructuras ya estudiadas, porque no es parte de una estructura anidadas. Para definir este campo, empezamos con la variable «teacher» a la que añadimos el nombre de grupo «descript», y entonces debemos describir que fichero de la estructura anidada deseamos, por lo que asignamos «age». «Teacher» viene dado de la misma forma que «Age», pero a los 2 últimos campos se les ha asignado cadenas, usando «strcpy», función normalmente utilizada para estos menesteres.

Los nombres de las variables en la función «strcpy» son todavía nombres de variables, aunque estén compuestas de varias partes.

A la variable «sub» le son asignados valores sin sentido de muchas formas, pero en diferente orden, ya que no se precisa un orden determinado para hacer estas asignaciones. Finalmente, a un grupo de variables «student», se les asignan valores, con propósitos ilustrativos y, el programa finaliza. Ninguno de los valores se muestra en la pantalla dado que ya lo hicimos con varios en los últimos ejemplos.

 

MÁS ACERCA DE LAS ESTRUCTURAS

Es posible seguir anidando estructuras. No existe límite para las estructuras en un programa, no obstante recomendamos no utilizar más de 3 para no crear confusión al programador, ya que la máquina se aclara perfectamente. Además, se pueden incluir tantas estructuras como se desee en un nivel de estructura, como por ejemplo definiendo esta estructura superior a «alldat», y usando «alldat» como complemento a «person». La estructura person podría ser incluida en «alldat» dos o tres veces más, como se quiera, como punteros de «alldat».

Una estructura puede contener arrays u otras estructuras, las cuales en cambio, pueden contener arrays, tipos simples u otras estructuras.

UNIONES, ¿QUÉ SON?

Explicado de manera simple, podríamos decir que las uniones le permiten ver los mismos datos con diferentes tipos, o usar un mismo dato con distintos nombres.


44UNION1.C

&nbsp;

main()

{

union {

int value; /*primera parte de la unión*/

struct {

char first; /*Estos dos valores son la segunda */

char second;

} half;

} number;

&nbsp;

long index;

&nbsp;

for (index = 12; index < 300000; index +=35231) {

number.value = index;

printf(" %15ld %6ld %6ld\n", number.value, number.half.first,

number.half.second );

}

}

En este ejemplo, tenemos 2 elementos para la unión, la primera parte  es un entero, «value» el cual está almacenado como una variable de 2 bits en algún lugar de la memoria del ordenador. El segundo elemento está constituido por 2 variables tipo caracter, «first» y «second». Estas variables se almacenan en la misma localización que «value», porque esto es lo que hace una unión. Permite almacenar datos de diferentes tipo en un mismo espacio físico. En este caso, podría ponerse un entero en «value», y recobrarlo luego en dos mitades, ubicadas en «first» y «second». Esta técnica se utiliza habitualmente para empaquetar bytes de datos cuando, por ejemplo, se están combinando datos para ser utilizados en los registros del microprocesador.

El acceso a los elementos de la unión es muy parecido a hacerlo en una estructura.

Una nota adicional acerca del programa: cuando se ejecuta en la mayoría de compiladores, los datos aparecerán por pantalla con dos «f» de guía, debido a la salida en formato hexadecimal de las variables «int» y «char», y añadiendo el signo a la izquierda. Convirtiendo los datos de tipo «char» en «int» antes de sacarlos por pantalla se podrían  evitar las «f». Esto supone la definición de nuevos tipos de variables enteras y la asignación de variables «char» a ellas.

 

OTRO EJEMPLO DE UNIÓN

Supongamos que se desea hacer una gran base de datos, incluyendo información de algunos tipos de vehículos. Sería absurdo incluir el número de hélices de un coche, o el número de ruedas de un barco. Para tener todos los datos correctos, necesitaríamos esos tipos de datos para cada clase de vehículo. Para que la base de datos sea eficiente, necesitaría diferentes tipos de datos para cada vehículo, aunque algunos podrían ser comunes, y otros exclusivos. Esto es lo que hace el siguiente ejemplo: definiremos una estructura completa, decidiremos cual de los varios tipos de datos pueden incluirse. Empezaremos por el principio, e iremos desarrollando:

45UNION2.C


#define AUTO 1

#define BOAT 2

#define PLANE 3

#define SHIP 4

&nbsp;

main()

{

struct automobile {  /* estructura de un automóvil          */

int tires;

int fenders;

int doors;

};

&nbsp;

typedef struct {     /* estructura de un barco o un avión   */

int displacement;

char length;

} BOATDEF;

&nbsp;

struct {

char vehicle;         /* ¨que tipo de vehículo?          */

int weight;           /* vehículo pesado                 */

union {               /* tipo de dato dependiente        */

struct automobile car;      /* parte 1 de la union    */

BOATDEF boat;               /* parte 2 de la union    */

struct {

char engines;

int wingspan;

} airplane;                 /* parte 3 de la union    */

BOATDEF ship;               /* parte 4 de la union    */

} vehicle_type;

int value;            /* valor del vehículo (en dólares) */

char owner[32];       /* nombre de los dueños            */

} ford, sun_fish, piper_cub;   /* 3 variables estructura    */

&nbsp;

/* define algunos campos como ejemplo                */

&nbsp;

ford.vehicle = AUTO;

ford.weight = 2742;              /* con el deposito lleno*/

ford.vehicle_type.car.tires = 5;  /* incluyendo repuesto */

ford.vehicle_type.car.doors = 2;

&nbsp;

sun_fish.value = 3742;           /* trailer no incluido  */

sun_fish.vehicle_type.boat.length = 20;

&nbsp;

piper_cub.vehicle = PLANE;

piper_cub.vehicle_type.airplane.wingspan = 27;

&nbsp;

if (ford.vehicle == AUTO) /* cual es en este caso     */

printf("El ford tiene %d ruedas.\n",ford.vehicle_type.car.tires);

&nbsp;

if (piper_cub.vehicle == AUTO) /* cual no es en este caso      */

printf("El avion tiene %d ruedas.\n",piper_cub.vehicle_type.

car.tires);

}

Primero definimos algunas constantes con el «#define», y comenzamos el programa en si. Definimos una estructura denominada «automobile», la cual contiene varios campos, con los que no debería existir confusión. No definimos variables, por ahora.

Acerca del autor: Rodrigo Paszniuk

Ingeniero Informático, amante de la tecnología, la música, el ciclismo y aprender cosas nuevas.

Posts Relacionados

  • Estructuras y Protocolos en Swift 3
  • Manual intermedio de C++
  • ENTRADAS/SALIDAS STANDARD en C++
  • Manual básico de C++



SEGUÍNOS EN FACEBOOK


GITHUB