¡Acceso ilimitado 24/7 a todos nuestros libros y vídeos! Descubra la Biblioteca Online ENI. Pulse aquí
¡Acceso ilimitado 24/7 a todos nuestros libros y vídeos! Descubra la Biblioteca Online ENI. Pulse aquí

Las estructuras de datos: struct y typedef struct

Objetivos del capítulo

En este capítulo se trata de crear nuevos tipos de datos y utilizarlos en las funciones.

Presentación

En los ejemplos de los capítulos anteriores, se han utilizado los tipos básicos (int, float…) y las tablas de estos tipos básicos.

Puede ser interesante crear nuevos tipos de datos adaptados a los problemas de las aplicaciones que se han de resolver.

Si para cada estudiante de una formación queremos guardar su número de identificación y su nombre, es práctico crear un tipo de datos ESTUDIANTE que agrupe estos dos datos. Esto es lo que se muestra en el siguiente ejemplo.

Estructura de datos

1. Palabra clave struct

La siguiente declaración crea un nuevo tipo de datos llamado ESTUDIANTE. No hay ninguna asignación de memoria.

numero y nombre son los campos de la estructura.

struct ESTUDIANTE  
{  
   int numero;             /* Numero del estudiante            */  
   char nombre[51];        /* Nombre del estudiante            */  
}; 

int main()  
{ 

La siguiente instrucción asigna una zona de memoria de tipo ESTUDIANTE. Se reserva un entero y 51 char:

    struct ESTUDIANTE s; 
images/106-1.png

Con el compilador de C++, no es necesario repetir la palabra «struct». La declaración ESTUDIANTE s es suficiente, pero esto no es estándar.

Las siguientes instrucciones inicializan los dos campos de la variable s.

Utilizan el operador . (point), que permite designar un campo de la estructura:

  • s.numero es una variable int como cualquier otra. Aquí, inicializada con un 10.

  • s.nombre es una tabla de char como cualquier otra. Se rellena con la cadena "Pie".

    s.numero = 10;  
    strcpy(s.nombre, "Pie"); 
images/106-2.png

A continuación se muestran las instrucciones que permiten la visualización de los campos y de sus direcciones:

   printf("Estudiante: %3d  %s\n\n"...

Punteros sobre estructuras, operador ->

La siguiente declaración reserva un espacio en memoria (un entero), destinado a contener la dirección de una variable de tipo ESTUDIANTE:

int main()  
{  
   ESTUDIANTE* pEstudiante; 
images/106-4.png

La siguiente instrucción permite la asignación dinámica de una variable de tipo ESTUDIANTE. La dirección de esta zona se asigna al puntero pEstudiante:

    pEstudiante = (ESTUDIANTE*) calloc(1, sizeof(ESTUDIANTE)); 
images/106-5.png

Las siguientes instrucciones rellenan los campos numero y nombre apuntados por pEstudiante:

    pEstudiante->numero = 10;  
    strcpy(pEstudiante->nombre, "Pie"); 
  • pEstudiante es un puntero sobre una variable de tipo ESTUDIANTE.

  • *pEstudiante es la variable apuntada.

  • (*pEstudiante).numero es la variable numero de la variable ESTUDIANTE apuntada.

La instrucción pEstudiante->numero = 10; podría escribirse: (*pEstudiante).numero = 10;

   printf("Estudiante: %3d  %s\n\n", pEstudiante->numero, pEstudiante->nombre);  
  
   return 0;  
} 

A continuación se muestra el resultado de la ejecución de este programa:

images/106-6.png

Para acceder a una variable correspondiente a un campo de una estructura (ejemplo con ESTUDIANTE):

Utilizar la sintaxis: s.numero si s es una variable de tipo ESTUDIANTE.

Utilizar la sintaxis: ps->numero...

Estructuras que contienen estructuras

Una vez definida, una estructura se puede utilizar como cualquier tipo, por ejemplo en otra estructura:

typedef struct  
{  
   char calle[51];  
   char codigo_postal[6];  
   char ciudad[51];  
} DIRECCION;  
  
typedef struct  
{  
   int numero;  
   char nombre[51];  
   DIRECCION direccion;  
} EMPLEADO;  
  
int main()  
{  
   EMPLEADO empleado; 
   empleado.numero = 10;  
   strcpy(empleado.nombre, "Ganso Común"); 
   strcpy(empleado.direccion.calle, "Islas Pitiusas, 1 "); 
   strcpy(empleado.direccion.codigo_postal, "28290"); 
   strcpy(empleado.direccion.ciudad, "Las Rozas"); 
  
   printf("Empleado: %3d  %s\n\n%s\n%s\n%s\n", empleado.numero,  
          empleado.nombre,  
          empleado.direccion.calle,  
          empleado.direccion.codigo_postal,  
          empleado.direccion.ciudad);  
  
   return 0;  
} 

A continuación...

Trabajo práctico: estructuras de datos

1. Objetivo

Utilizar estructuras de datos en el diseño de funciones.

2. Tema

Se trata de retomar el TP funcFracciones (capítulo Las funciones), usando una estructura de datos FRACCION:

typedef struct  
{  
   int Num;  
   int Den; } FRACCION; 

3. Estructuras de datos: proposición de corrección

typedef struct  
{  
   int Num;  
   int Den;  
} FRACCION; 
  • La función introduceValor() debe rellenar una variable de tipo FRACCION; por lo tanto, modificarla. Hay que pasarle la dirección de la fracción que se ha de rellenar.

  • La función visualizar() muestra la fracción sin modificarla. Podemos pasar directamente la fracción que se ha de mostrar.

  • La función suma() recibe como argumentos las dos fracciones que se han de sumar y utiliza un valor de retorno de tipo FRACCION para devolver el resultado.

  • La función pgcd() no cambia. No tiene un enlace directo con FRACCION. Calcula el pgcd de dos enteros, ya sea en una fracción o no.

Los prototipos de las funciones son:

void introduceValor(FRACCION*);  
void visualizar(FRACCION);  
FRACCION suma(FRACCION, FRACCION);  
int pgcd(int, int); 

int main()  
{  
   FRACCION f1, f2, f3;  
  
 ...