Una estructura es un conjunto de variables que se referencian con

Anuncio
Una estructura es un conjunto de variables que se referencian con un único
nombre. Esto es muy útil cuando queramos mantener junta información relacionada.
Para definir una estructura, utilizamos la palabra clave struct. Esta palabra le indica al
compilador que lo que viene a continuación es una estructura. La forma general para
definir una estructura es la siguiente:
struct nombre_estructura
{
tipo variable1;
tipo variable2;
...
...
tipo variablei [=expresión]
...
...
tipo variableN;
} lista_variables_estructura;
Con esta definición realmente haremos 2 cosas: por una parte, estamos definiendo
una plantilla de estructuras, la cual tomará el nombre que indique el parámetro
nombre_estructura, y por otra parte, estamos definiendo una serie de variables con la
forma de la plantilla definida. Estas variables son las que vendrían dadas por el
parámetro lista_variables_estructura. Cada campo de una estructura puede ser
inicializado en la declaración mediante una expresión de la misma forma a como se
hacía al declarar una variable de un tipo básico. Un ejemplo más concreto podría ser la
siguiente estructura:
struct Datos_Persona
{
char nombre[20];
char apellido1[20];
char apellido2[20];
char calle[50];
char ciudad[20] = "Sevilla";
unsigned long DNI;
} pers1, pers2, pers3, pers4;
Si posteriormente deseamos crear más variables utilizando la plantilla de
estructura datos_persona, bastaría con declararla de la siguiente forma:
struct Datos_Persona nueva_persona;
Hay que tener cuidado al elegir el lugar donde definimos la plantilla de estructura.
Lo más normal es declararla globalmente para que pueda ser utilizada en cualquier lugar
del programa.
A la hora de definir la plantilla de estructura podemos omitir, o bien, el parámetro
nombre_estructura, o bien, el parámetro lista_variables_estructura. En el caso de que se
omita el parámetro nombre_estructura, sólo podremos usar la plantilla para definir las
variables que aparezcan en el parámetro lista_variables_estructura. Si posteriormente
queremos declarar alguna otra variable utilizando esta plantilla, tendremos que volver a
definirla. Si el parámetro que omitimos es lista_variables_estructura, lo que habremos
hecho es crear una plantilla de estructura sin variables asociadas, las cuales podremos
crear en cualquier momento, usando el modo de declaración de estructura visto
anteriormente, es decir:
struct nombre_estructura nombre_variable_nueva;
En ningún caso podremos omitir, a la vez, el nombre_estructura y la
lista_variables_estructura.
Veamos ahora como podemos acceder a los elementos individuales que forman
las estructuras. Para dichos accesos se utiliza el operador ".". Veamos un ejemplo de
acceso a una estructura. Supongamos que tenemos la siguiente estructura:
struct coordenada
{
int x;
int y;
int z;
} a, b, c;
Para llenar la variable estructura "a" bastaría con hacer:
a.x = 5;
a.y = 23;
a.z = 10;
En cualquier momento podremos leer estos datos:
int eje_x, eje_y, eje_z;
eje_x = a.x;
eje_y = a.y;
eje_z = a.z;
Otra operación que podremos realizar son asignaciones entre variables estructuras
con la misma plantilla:
c = a;
b = c;
Los tipos de los elementos individuales de una estructura pueden ser simples (int,
float, char, …) o complejos (array, otra estructura, …). Veamos un ejemplo de una
plantilla de estructura que combina elementos individuales simples y complejos.
struct fecha
{
int dia;
int mes;
int anyo;
};
struct hora
{
int horas;
int minutos;
};
struct ficha
{
char nombre[20];
char apellidos[40];
struct fecha dia_nacimiento;
struct hora hora_nacimiento;
};
Si queremos definir una variable tipo ficha, y queremos poner la fecha de
nacimiento haremos:
struct ficha persona;
persona.fecha.dia = 20;
persona.fecha.mes = 2;
persona.fecha.anyo = 2001;
Otra posibilidad frecuentemente utilizada que se le ofrece al programador es la de
definir tablas de estructuras. De esta manera se permite gestionar una gran cantidad de
información fácilmente. Un ejemplo sencillo de esto sería por ejemplo una matriz de
coordenadas. Teniendo en cuenta la estructura coordenada definida más arriba
podríamos definir la siguiente matriz:
struct coordenada matriz1[10][10];
En este caso una posible inicialización de la anterior matriz en el que todos sus
componentes toman como valor el origen de coordenadas quedaría de la siguiente
manera:
for (cont_filas=0; cont<10; cont_filas++)
{
for (cont_columnas=0; cont_columnas<10; cont_columnas++)
{
matriz[cont_filas][cont_columnas].x = 0;
matriz[cont_filas][cont_columnas].y = 0;
matriz[cont_filas][cont_columnas].z = 0;
}
}
Ejemplos más complejos se podrían crear a partir de la estructura ficha de forma
que se pudieran gestionar los datos de toda una población de individuos. En este caso
tendríamos por ejemplo:
struct ficha poblacion[100]; // Vector que sirve para gestionar los
datos personales de 100 individuos.
Al igual que con el resto de tipos de variables, C permite crear variables punteros
a estructuras. La forma de declarar estas variables es:
struct nombre_estructura *nombre_varible_estructura;
Para poder acceder a los elementos individuales de una variable puntero a
estructura se utiliza el operador -> (el operador, denominado comunmente flecha, está
formado por un signo menos seguido de un signo de mayor, sin ningún espacio en
blanco entre ellos). Siguiendo con el ejemplo anterior de las coordenadas, vamos a
definir un puntero a una variable de estructura de la siguiente forma:
struct coordenada a, b, *p, *q;
a.x = 5;
a.y = 23;
a.z = 10;
b = a;
p = &b; /* &b nos devuelve la dirección de la estructura b */
p->x = 2;
p->y = a.y;
p->z = a.z;
q = p; /* p y q apuntan a la misma estructura */
Al igual que ocurría en el apartado anterior también existe la posibilidad de
declarar tablas de estructuras. El formato sería el siguiente:
struct nombre_estructura *nombre_varible_estructura[N];
o
struct nombre_estructura *nombre_varible_estructura[N][M];
Por supuesto también se pueden declarar tablas de punteros a estructuras de más
de dos dimensiones pero al igual que ocurría con la declaración de tablas de tipos de
datos básicos, no suelen ser muy usadas.
Un ejemplo de declaración de un vector de punteros a estructuras y un acceso al
campo de una estructura sería la siguiente:
struct coordenada coor1, *vector_punteros_coordenadas[10];
vector_punteros_coordenadas[4] = &coor1;
vector_punteros_coordenadas[4]->y = 2;
Al igual que ocurría con los punteros a tipos básicos de datos también se pueden
pasar punteros a estructuras en las llamadas a funciones. Así por ejemplo tendríamos:
struct coordenada coordenada1, *p_coordenada1;
flota distancia;
coordenada1.x = 5;
coordenada1.y = -11;
p_coordenada1 = &coordenada1;
cambiar_a_punto_simétrico_en_cuadrante (p_coordenada1);
ó
cambiar_a_punto_simetrico_en_cuadrante (&coordenada1);
...
...
...
/* La siguiente función intercambia la coordenada x por la y */
void cambiar_a_punto_simétrico_en_cuadrante(struct coordenada
*c)
{
int aux;
aux = (*c).x;
(*c).x = (*c).y;
(*c).y = aux;
}
Nótese la equivalencia entre la notación c->x y (*c).x
En el lenguaje C, cuando hablamos de unión nos estamos refiriendo a una porción
de memoria compartida por varias variables, las cuales pueden ser de distintos tipos.
Para declarar una unión usamos la palabra clave union de la siguiente forma:
union nombre_union
{
tipo variable1;
tipo variable2;
...
...
tipo variableN;
} lista_variables_union;
Como se ve, la forma de declaración de declaración es similar a la de una
estructura, de forma que podremos declarar una variable, o bien colocando su nombre al
final de la declaración inicial, o posteriormente, utilizando una declaración aparte como
muestra el siguiente código:
union nombre_union nombre_variable_nueva;
La forma de funcionamiento de las uniones es muy simple. Cuando definimos
una unión y declaramos variables asociadas, el compilador reservará para cada variable,
un espacio de memoria cuyo tamaño coincidirá con el tamaño del elemento más grande
que se defina dentro de la unión. Supongamos que tenemos la siguiente declaración:
union prueba_union
{
char letra;
char cadena[8];
int numero;
} u1;
El compilador reservará, para la variable u1, 8 bytes de memoria (que
corresponde con el tamaño del elemento cadena), de forma que en caso de acceder al
elemento letra, estaremos accediendo al primer byte de la variable, mientras que si
accedemos al elemento numero, estaremos accediendo a los dos primeros bytes de la
variable. Por último, si accedemos al elemento cadena estaremos accediendo a todos los
bytes de la variable.
Una enumeración es un conjunto de constantes enteras con nombre, que
especifica todos los valores válidos que una variable de este tipo puede tener. La forma
de definir una enumeración es:
enum nombre_enum{lista_de_enum} variables_de_enum;
Veamos un ejemplo:
enum color{blanco,
color_mesa;
amarillo,
rojo,
verde,
azul,
marron,
negro}
Como con las estructuras, C permite definir posteriormente más variables
enumeradas del tipo color, la forma de hacerlo sería la siguiente:
enum color color_coche;
Una vez definidas las variables enumeradas, las siguientes operaciones serían
válidas:
color_mesa = verde;
color_coche = color_mesa;
if(color_mesa == azul)
printf("La mesa es de color azul\n");
switch(color_coche)
{
case blanco:
printf("El coche es de color blanco\n");
break;
case amarillo:
printf("El coche es de color amarillo\n");
break;
case rojo:
printf("El coche es de color rojo\n");
break;
case verde:
printf("El coche es de color verde\n");
break;
case azul:
printf("El coche es de color azul\n");
break;
case marron:
printf("El coche es de color marron\n");
break;
case negro:
printf("El coche es de color negro\n");
break;
}
Para poder definir nuevos nombres de tipos de datos, usamos la palabra clave
typedef. Con esto, realmente no estamos creando un nuevo tipo de datos, sino que se
define un nuevo nombre a un tipo ya existente. También podemos usar typedef para
asignar un nombre de tipo a una estructura o a una enumeración, de forma que para
declarar las variables de estos tipos no necesitaremos precederlos de las palabras clave
struct o enum, respectivamente. La forma general de la sentencia typedef es:
typedef tipo nombre_nuevo_tipo;
Algunos ejemplos podrían ser:
typedef int ENTERO;
typedef unsigned char BYTE;
typedef struct fecha FECHA;
De forma que podremos definir variables como:
ENTERO *e1, e2;
BYTE *b1, b2;
FECHA *f1, f2, lista_fechas[20];
Un uso típico al definir estructuras es:
typedef struct
{
float x,y,z;
} coordenada;
Si queremos definir una variable de este tipo de estructura basta con poner:
coordenada a;
Y a será una variable de estructura coordenada, lo que clarifica el código.
Descargar