Estructuras

Una estructura es un conjunto de datos, posiblemente de tipos diferentes, agrupadas bajo un mismo nombre, para hacer más eficiente su manejo.

Las estructuras ayudan a organizar datos complicados, particularmente en programas grandes, ya que permiten tratar como una unidad a un conjunto de variables relacionadas, en lugar de tratarlas como entidades independientes.

Un buen criterio de uso de estructuras establece que la definición de una estructura debe ir acompañada por la definición de un conjunto de funciones que se encargan de realizar la manipulación directa de la nueva entidad creada.

Definición de estructuras en Lenguaje C

Una estructura se define en lenguaje C a través de la siguiente sintáxis:

struct Nombre
{
  tipo1 Campo1;
  tipo2 Campo2;
  ...
  tipoN CampoN;
};

La declaración

struct Nombre Var1;

Declara una variable del tipo "struct Nombre", esto es, el compilador reserva la cantidad de memoria sufuciente para mantener la estructura íntegra (es decir espacio para almacenar Campo1, Campo2, ..., CampoN). Cuando se hace referencia a la variable Var, se esta haciendo referencia a la estructura íntegra.

Inicialización de estructuras

Se puede inicializar una estructura externa o estática añadiendo a su definición la lista de inicializadores:

struct Fecha
{
  int Dia;
  char *Mes;
  int Anio;
};

struct Fecha Hoy = {8,"Mayo",1991},
             VarFecha;
...
VarFecha = Hoy;

La asignación VarFecha = Hoy copia la estructura integra Hoy en VarFecha. Cuando dentro de los campos de una estructura aparecen punteros y uno realiza este tipo de asignación, se esta copiando tambien los valores de los punteros, de tal manera que se puede estar haciendo referencia a un dato desde dos puntos diferentes lo que puede causar efectos no deseados y un potencial peligro para la aplicación.

Referencia de campos de una estructura

Un campo de una estructura se utiliza como una variable más. Para referenciar un campo de una estructura se emplea el operador ".".

Ejemplo:

Hoy.Dia = 24;
Hoy.Mes = "Agosto";
Hoy.Anio = 1991;

Ejemplo para verificar año bisiesto:

Bisiesto = Fecha.Anio % 4 == 0 &&
           Fecha.Anio % 100 != 0 ||
           Fecha.Anio % 400 == 0;

Las estructuras se pueden anidar:

struct Person
{
   char Name [NAMESIZE];
   char Adress[ADRSIZE];
   long ZipCode;
   double Salary;
   struct Fecha Nacimiento;
};

Para referenciar un campo de una estructura interna se utiliza la misma sintáxis, referenciando campos interno dentro de campos:

struct Person Juan;
Juan.Nacimiento.Dia = 14;

Punteros a Estructuras

Una vez definida las estructuras, se utilizan en forma análoga a los tipos estándar de datos, por lo tanto se pueden declarar arreglos de estructuras, y tambien punteros a estructuras. Se pueden declarar variables que apunten a estructuras:

Struct Fecha *FechaPtr;
Struct Fecha Hoy;
FechaPtr = &Hoy;

La referencia a un campo de una estructura a través de un puntero se realiza mediante el operador "->".

FechaPtr -> Dia = 15;
FechaPtr -> Mes = "Octubre";

Arreglos de Estructuras

En el siguiente ejemplo se observa como se declara un arreglo de estructuras, definidas de manera tal que mantienen la información necesaria para describir un intervalo, y la cantidad de cuentas que caen en ese intervalo como para armar un histograma.

#include <stdlib.h>
#include <stdio.h>

struct Intervalo
{
  double Lower,   /* Límite inferior del intervalo  */
         Upper;   /* Límite superior del intervalo  */
  int    Counter; /* Cantidad de puntos dentro      */
};

#define NUM_INTER 100

main()
{
  struct Intervalo Inter[NUM_INTER];
  int Index;
  double Delta = RAND_MAX/NUM_INTER;

/* Inicialización del vector de estructuras          */
  for (Index=0; Index<NUMINTER; Index ++)
  {
    Inter[Index].Counter = 0;
    Inter[Index].Lower = Delta*Index;
    Inter[Index].Upper = Delta*(Index+1);
  }

  for (Index=0; Index<10000; Index++)
    Inter[rand()/Delta].Counter++;

/* impresión de resultados                           */
  for (Index=0; Index<NUM_INTER; Index++)
    printf("[%lf,%lf]=%d/n", Inter[Index].Lower,
           Inter[Index].Upper, Inter[Index].Counter);
}