Capítulo 12
Estructuras
En este capítulo aprenderá:
• Qué son las estructuras.
• Cómo manejár las estructuras.
• Cómo tener distintos tipos de datos en un mismo array.
222 Capítulo 12
Introducción
Los arrays nos permiten almacenar distintos datos, pero todos del mismo tipo.
Recordemos aquel programa del capítulo de arrays en el que teníamos un
array bidimensional con los números de expediente, tres notas y la nota
media de seis alumnos. Todos estos datos eran del mismo tipo. Si hubiésemos
querido añadir un dato más como el nombre del alumno no hubiera sido
posible, porque el nombre es un array de tipo char y los otros datos son de
tipo int.
Por otro lado, almacenar los datos de los alumnos en un array bidimensional
no está mal, pero sería todavía mejor almacenarlos de alguna forma más
ordenada.
En la vida cotidiana, y recurriendo al papel, cuando queremos almacenar los
datos de un alumno utilizamos una ficha, en la que incluso se puede poner
una foto, como la de la figura 12.1.
Figura 12.1. Ficha en papel de un alumno.
A "Nombre", "N° Expediente", "Nota 1", "Nota 2", "Nota 3" y "Nota Media"
nos referimos como campos. La idea es crear y utilizar esas fichas en nuestros
programas, pero sin fotos, claro. En programación, esas fichas son las
estructuras y los campos de las fichas son variables declaradas dentro de una
estructura.
Las estructuras admiten variables de distinto tipo y, también, podemos crear
arrays unidimensionales de una estructura, es decir, cada celda almacenará
una estructura. De esta manera conseguimos juntar variables de distintos
tipos en un array. ¡Hemos resuelto el problema!
En la figura 12.2 se muestra una representación gráfica de un array de estruc-
turas con cuatro celdas.
Estructuras 223
0 1 2 3
Figura 12.2. Representación gráfica de un array de estructuras.
Todo es muy parecido a la vida cotidiana. Un array unidimensional de
estructuras con cuatro celdas es igual que tener un pequeño montón con
cuatro fichas. Si queremos buscar la ficha de un alumno para ver su nota
media comprobamos ficha a ficha su nombre hasta encontrarle y, después,
consultamos su nota media. En un array de estructuras comprobaríamos
celda a celda hasta encontrar el nombre del alumno buscado y, entonces,
consultaríamos su nota media.
Declaración
Para utilizar una estructura primero hay que crearla, que es como crear un
molde de imprenta para una ficha, pero que en principio no sirve para
almacenar datos. Posteriormente, declararemos variables de esa estructura,
que es como obtener un ejemplar de una ficha a partir del molde. Esa
variable de la estructura contiene los campos donde ya podemos almacenar
los datos. En la figura 12.3 podemos ver una representación de lo que
haremos en código.
1o. Creación del molde 2o. Creación de la ficha 3o. Ficha
1o. Creación de 2o. Declaración de 3o. Variable de
la estructura la variable de la la estructura
estructura
Figura 12.3. Paso de la creación de la estructura a la variable de la estructura.
224 Capítulo 12
La forma general de crear estructuras es:
struct identificador_s {
tipo identificador_campol;
tipo identificador_campo2;
tipo identificador_campoN;
};
Donde struct es una palabra reservada y necesaria para crear la estruc-
tura, e identif icador_s es el nombre que daremos a la estructura, que
sería igual al nombre del molde. A continuación, y entre llaves, se declaran
las variables, que se corresponden con los campos de la ficha. Observe que al
final de la definición de la estructura hay punto y coma (;).
A las estructuras les damos un nombre porque podemos tener más de una y
necesitaremos identificarlas de alguna manera. Para crear una estructura
equivalente a la ficha de la figura 12.1 escribimos:
struct Tficha {
char nombre[30];
int numero_exp;
int nota_l,
nota_2, nota_3;
int nota_media
} ;
El nombre de esta estructura es Tficha y contiene estos 6 campos:
nombre, numero_exp, nota_l, nota_2, nota_3 y nota_media.
Como puede ver, las variables se declaran como siempre.
No olvide el punto y coma tras la definición.
Las definiciones de estructuras se pueden escribir dentro de la función
main, pero es conveniente escribirlas encima de ésta para que puedan ser
accesibles por todo el programa:
/* Aqui van los #include */
/* Aqui van los #define */
struct Tficha {
char nombre[30]; int numero_exp; int nota_l,
nota_2, nota_3; int nota_media
} ;
int main (void)
{
/* Aqui va el codigo del programa principal */
}
Ya tenemos la estructura. Para declarar una variable de una estructura la
sintaxisidentificador
struct es: s variable s;
Estructuras 225
Donde i d e n t i f i c a d o r _ s es el nombre que le dimos a la estructura y
v a r i a b l e _ s es el identificador de la variable que vamos a crear de esa es-
tructura. Esta sintaxis sigue siendo la misma de siempre para declarar va-
riables:
tipo identificador;
pero en este caso s t r u c t i d e n t i f i c a d o r _ s actúa como el tipo de dato de
la variable. Para declarar una variable de la estructura anterior escribimos:
struct Tficha {
char nombre[30];
int numero_exp;
int nota_1, nota_2, nota_3;
int nota_media
};
int main (void)
{
struct Tficha mi_ficha;
}
Donde m i _ f i c h a es una variable de la estructura T f i c h a . También podemos
declarar variables de estructuras de la forma:
struct Tficha mi_ficha1, mi_ficha2, mi_ficha3;
Nota: _____________________________________________
Como en la declaración de una variable de una estructura aparecen
tres palabras (struct, identificador de la estructura e identificador de
la variable de la estructura), para no confundir el identificador de la
estructura con el de la variable, al nombre de la estructura le
podemos añadir una letra "T" o la palabra "tipo" de alguna manera,
por aquello de que junto con la palabra reservada struct actúa como
un tipo de dato.
Entonces, si la sintaxis para declarar un array unidimensional es:
tipo identificador[Tamaño];
y queremos declarar un array unidimensional de 10 celdas con estructuras
T f i c h a , como s t r u c t T f i c h a actúa como un tipo de dato, tenemos que
escribir:
struct Tficha mi_array[10];
El resultado es un array llamado m i _ a r r a y de 10 celdas, y en cada celda hay
una estructura T f i c h a .
226 Capítulo 12
También se pueden declarar variables de una estructura a la vez que se de-
fine. La sintaxis es:
struct identificador_s {
tipo identificador_campo1;
tipo identificador_campo2;
tipo identificador_campoN;
} variable_s;
Donde variable s es el identificador de la variable de la estructura llama-
da identificador_s.
Ejemplo:
struct Tficha {
char nombre[30];
int numero_exp;
int nota_1, nota_2, nota_3;
int nota_media
} mi_ficha;
Acceso a los campos
Ahora nos falta saber cómo acceder a los campos de las variables de las
estructuras. Pues bien, es tan fácil como escribir la siguiente sintaxis:
variable_s.identificador_campo
Donde variable_s es el identificador de la variable de la estructura, e identif
icador_campo es el nombre de la variable declarada en la estructura a la que
queremos acceder. Observe que entre los dos identificadores hay un punto.
Así, para acceder al campo nota_l de la variable mi_ficha (que es una es-
tructura Tficha) escribimos primero el nombre de la variable de la estruc-
tura, un punto y el nombre del campo:
mi_ficha.nota_1
La idea es que cuando accedemos a un campo con lo que estamos trabajando
realmente es con una variable, una simple variable de las de siempre, pero
que está dentro de una estructura. Y como es una simple variable podemos
hacer todas las siguientes operaciones y más, pero siempre indicando a qué
variable de estructura pertenece:
mi_ficha.nota_l = 6; /* Asignarle un valor. */
printf ("%d", mi_ficha.nota_l); /* Mostrar su valor en pantalla. */
scanf ("%d", &mi_ficha.nota_l); /* Asignarle un valor por teclado. */
mi_ficha.nota_l = mi_ficha.nota_l + 2; /* Incrementar su valor. */
mi [Link] 1—; /* Decrementar su valor. */
Estructuras 227
Veamos el ejemplo de un programa en el que se crea una estructura con tres
campos: nombre, edad y teléfono. El usuario debe rellenar estos datos por
teclado. Posteriormente se mostrarán los datos de la estructura.
#include <stdio.h>
/* Creamos la estructura"tipo_ficha".*/
struct tipo_ficha {
char nombre[50];
int edad;
char telefono[20] ;
};
int main (void)
{
/* Declaramos un variable de la estructura "tipo_ficha". */
struct tipo_ficha persona;
/* Pedimos los datos al usuario y los almacenamos en cada
uno de los campos de la estructura. */
printf ("Escriba su nombre: ");
gets ([Link]);
printf ("Escriba su edad: ");
scanf ("%d", [Link]);
fflush (stdin);
printf ("Escriba su telefono: ");
gets ([Link]);
/* Mostramos los datos almacenados en la estructura. */
printf ("\nLa edad de %s es %d", [Link], [Link]);
printf ("\ny su telefono es %s.", [Link]);
/* Hacemos una pausa hasta que el usuario pulse Intro */
fflush(stdin);
printf("\n\nPulse Intro para finalizar...");
getchar();
}
Si el nombre del usuario es Ana, su edad 10 y su teléfono 000-000-000, el es-
tado de la variable persona sería el de la figura 12.4.
Figura 12.4. Estado de la variable persona.
El resultado en pantalla del programa es el de la figura 12.5.
228 Capítulo 12
Figura 12.5. Resultado del programa.
Estructuras y arrays
Ya hemos dicho en el apartado "Declaración" cómo se crean arrays de estruc-
turas. Pero ¿cómo se manejan?
Si tenemos la siguiente estructura:
struct tipo_libro {
char
titulo[30];
int paginas;
};
para registrar libros y su número de páginas, también necesitaremos un array
de esta estructura, porque tendremos varios libros. Si suponemos que tene-
mos 10 libros la declaración es:
struct tipo_libros libros[10];
Donde libros es el nombre del array y struct tipo_libros el tipo de
dato.
Para acceder al campo paginas de la estructura almacenada en la celda 0
escribimos el nombre del array, el número de la celda (entre corchetes) donde
está la estructura con la que queremos trabajar, un punto y el nombre del
campo al que queremos acceder:
libros[0].paginas
Así es como se accede a cualquier campo de las estructuras de un array. Si
queremos rellenar por teclado el campo tituloypaginas de la celda 0,
escribimos:
Estructuras 229
printf ("Escriba el titulo del libro: ") ; gets
(libros[0].titulo);
printf ("Escriba el numero de paginas del libro: "); scanf
("%d", Slibros[0].titulo);
Y si queremos almacenar el título y el número de páginas de 10 libros pode-
mos hacerlo con un bucle f or:
for (celda=0; celda<=9; celda++)
{
printf ("\nEscriba el titulo del libro %d: ", celda+1);
gets (libros[celda].titulo);
printf ("Escriba el numero de paginas del libro %d: ", celda+1);
scanf ("%d", Slibros[celda].titulo);
}
Hagamos ahora, utilizando las estructuras, el programa del capítulo de
arrays en el que teníamos un array bidimensional con los números de
expediente, tres notas y la nota media de seis alumnos. Necesitaremos una
estructura con cinco campos: número de expediente, nota 1, nota 2, nota 3 y
nota media. Si tenemos 6 alumnos necesitaremos un array unidimensional
con 6 celdas de estas estructuras (véase la figura 12.6).
0 1 2 3 4 5
N° Expediente: ___ N° Expediente:____ N° Expediente: ___ N° Expediente: ___ N° Expediente: ___ N° Expediente: ___
Nota 1 : ___ Nota 1 : ___ Nota 1 : __ Nota 1: ___ Nota 1 : __ Nota 1 : __
Nota 2: ___ Nota 2: ____ Nota 2: ___ Nota 2: ___ Nota 2: ___ Nota 2: ___
Nota 3: ___ Nota 3: ____ Nota 3: ___ Nota 3: ___ Nota 3: ___ Nota 3: ___
Nota Media: ____ Nota Media: ___ Nota Media: ___ Nota Media: ___ Nota Media: ___ Nota Media: ___
Figura 12.6. Array de estructuras.
El programa pide al usuario que rellene el número de expediente de cada
alumno y sus tres notas. Posteriormente, se calcula la nota media de cada
alumno y se muestra el número de expediente del alumno con la mayor nota
media y dicha nota.
#include <stdio.h>
struct tipo_alumno {
int numero_exp;
int notal, nota2, nota3;
int nota_media;
};
int main (void)
{
struct tipo_alumno alum[6]; /* Array de estructuras. */
int n; /* Para recorrer las celdas. */
int media_mayor; /* Almacena la media mayor. */
int mejor_exp; /* Almacena el expediente con mayor media. */
int suma;
230 Capítulo 12
/* Rellenamos los campos expediente, notal, nota2 y nota3 de cada
alumno. */ for (n=0; n<=5; n++)
{
/* Pedimos el numero de expediente y las tres notas. */
printf ("\nEscriba el numero de expediente: ");
scanf("%d", &alum[n].numero_exp);
printf ("\nEscriba la nota 1: ");
scanf ("%d", &alum[n].notal);
printf ("\nEscriba la nota 2: ");
scanf ("%d", &alum[n],nota2);
printf ("\nEscriba la nota 3: ");
scanf ("%d", &alum[n].nota3);
}
/* Calculamos la nota media de cada alumno. */ for (n=0; n<=5; n++)
{
suma = alum[n].notal + alum[n].nota2 + alum[n].nota3; alum[n].nota_media
= suma / 3;
}
/* Calculamos la nota media mayor y obtenemos dicha nota.
Partimos de la idea de que la mayor nota es 0. */
media_mayor=0;
for (n=0; n<=5; n++)
{
/* Si estamos ante una nota mayor que la almacenada en
media_mayor, entonces esta nueva nota pasa a ser la media
mayor y almacenamos el numero de expediente de ese alumno.
*/ if (alum[n].nota_media > media_mayor)
{
media_mayor = alum[n].nota_media;
mejor_exp = alumfn].numero_exp;
}
}
/* Mostramos en la pantalla unos mensajes que indican el numero
de expediente del alumno con la nota media mayor y dicha nota. */
printf ("\n\nLa mejor media:");
printf ("\n\tExpediente: %d", mejor_exp);
printf ("\n\tNota Media: %d\n", media_mayor);
/* Hacemos una pausa hasta que el usuario pulse Intro */
fflush(stdin);
printf ("\n\nPulse Intro para finalizar...");
getchar ();
}
El resultado final de este programa es exacto al del capítulo de arrays, pero
ya no tenemos que preocuparnos de las filas y columnas en el array, y si
queremos podemos añadir un campo que sea el nombre del alumno. Más
facilidades y más posibilidades.
Estructuras 231
Ejercicios resueltos
Intente realizar los siguientes ejercicios. Encontrará la solución al final de
este libro.
1. Escriba la definición y dibuje las siguientes estructuras:
• Una estructura que permita almacenar una fecha. Tendrá 3 campos:
día, mes y año.
• Una estructura que sirva para catalogar los libros de una biblioteca.
Tendrá los siguientes campos: título, autor, tema, ISBN y número de
páginas. El ISBN es un número de identificación de 10 dígitos.
2. Realice un programa que almacene el nombre de seis jugadores de
videojuegos y la puntuación máxima de cada uno. Posteriormente, debe
mostrarse en pantalla el nombre del jugador con el mayor número de
puntos y el del jugador con el menor número de puntos.
Resumen
Una de las ventajas que ofrecen las estructuras es la de agrupar una serie de
datos bajo un nombre. Esto nos permite tener una visión más estructurada y
lógica del programa y sus datos.
Las estructuras también nos han resuelto el problema de almacenar datos de
distintos tipos en un mismo array.
Puede parecer que no tienen una gran utilidad, pero todas las características
que hemos mencionado son muy valiosas. En programación el orden, la cla-
ridad y la lógica son piezas clave.