void main

Anuncio
Fundamentos de Informática
ETSID
Tema 8: Estructuras.
Departamento de Sistemas Informáticos y Computación
Universidad Politécnica de Valencia
Índice
1. Introducción.
2. Declaración del tipo estructura.
3. Declaración de variables del tipo estructura.
4. Tipos definidos por el usuario
5. Estructuras anidadas.
6. Vectores de estructuras.
7. Inicialización.
8. Acceso a los miembros de una estructura.
9. Operaciones sobre estructuras.
10. Estructuras como parámetros.
1
1. Introducción
Una estructura es un tipo de dato
compuesto que permite almacenar datos de
diferente tipo (simples o estructurados). Se
referencia con un único nombre.
Ejemplo: con una misma variable se pueden
guardar el nombre de una persona, su dni,
su edad…
Cuando se usa un tipo entero, el tipo ya
está declarado, por lo que sólo hay que:
1. Declarar variables de tipo entero.
Cuando se usa un tipo estructura, el tipo
NO está declarado, por tanto se deben
realizar dos pasos:
1. Declarar el tipo estructura.
2. Declarar variables del tipo estructura.
2
¿En qué parte del programa se declaran las
estructuras?
1. El tipo estructura se declara fuera del main
y de las funciones para que sea global a
todo el programa.
2. Las variables del tipo estructura se
declaran en el programa principal (lo más
habitual) o en la función que las utiliza
(local).
2. Declaración del tipo
estructura
struct [nombre_estructura]
{
tipo_dato
miembro_1;
tipo_dato
miembro_2;
…
tipo_dato
miembro_n;
} [lista de variables];
3
z
Miembro o campo: cada uno de los datos de
la estructura (cada uno de ellos pertenece a un
tipo de datos).
z
Identificador o nombre de la estructura: tipo
de dato que se describe y del cual se podrán
declarar variables. Es opcional (puede no
declararse un tipo de dato y en su lugar
declarar variables directamente).
Ejemplo:
struct persona
{
char nombre[80];
int edad, sexo;
long int dni;
long int telefono;
};
Nombre del tipo:
identificador
(struct persona)
Miembros
4
3. Declaración de variables de
tipo estructura
z
z
Implícita
struct [nombre_estructura]
{
...
} variable1, variable2;
Explícita
struct nombre_estructura
{
…
};
Se pueden
combinar ambas
formas de declarar
variables.
struct nombre_estructura variable1, variable2;
struct
{
int a;
float b;
char c;
} s1, s2, s3;
struct coordenada
{
int a;
float b;
char c;
};
struct coordenada
{
int a;
float b;
char c;
} s1;
struct coordenada
s1, s2, s3;
struct coordenada
s2, s3;
5
Ejercicio
Declarar una estructura de datos para contener
los datos de una agenda personal:
struct agenda
{
char nombre[81];
unsigned long int telefono_fijo;
unsigned long int telefono_movil;
char direccion[101];
};
4. Tipos definidos por el
usuario
typedef tipo_dato nombre_tipo;
typedef char caracter;
caracter A, B, C;
typedef struct
{
unsigned long int num_tarjeta;
char tipo_cuenta;
float saldo;
} tipo_tarjeta;
typedef permite
cambiar de nombre
un tipo de datos.
tipo_tarjeta cliente;
6
typedef struct num_complejo
{
float real;
Se puede nombrar este tipo
float imaginaria;
estructura de dos formas:
} complejo;
complejo
o
struct num_complejo
complejo c1, c2, c3[800];
struct num_complejo c4, c5;
typedef struct
{
float real;
float imaginaria;
} complejo;
complejo c1, c2, c3[800];
struct num_complejo c4, c5;
No se puede,
porque no tiene
nombre con
struct
7
5. Estructuras anidadas
struct fecha
struct tarjetas
{
{
int dia;
long int num_tarjeta;
int mes;
char tipo_cuenta;
char nombre[80];
int año;
float saldo;
};
struct fecha ultimo_pago;
} cliente1, cliente2;
num_tarjeta
tipo_cuenta
struct fecha
{
int dia;
int mes;
int año;
};
nombre
saldo
ultimo_pago
dia
mes
año
Cuando una estructura está
anidada en otra, la anidada
debe estar escrita antes.
struct tarjetas
{
long int num_tarjeta;
char tipo_cuenta;
char nombre[80];
float saldo;
struct fecha ultimo_pago;
} cliente1, cliente2;
8
6. Vectores de estructuras
struct biblio
{
char titulo[80];
char autor[40];
float precio;
};
struct biblio libreria[100];
titulo
titulo
autor
autor
precio
precio
libreria[0]
libreria[1]
titulo
...
autor
precio
libreria[99]
7. Inicialización
struct fecha
{
int dia;
int mes;
int año;
};
struct tarjetas
{
long int num_tarjeta;
char tipo_cuenta;
char nombre[80];
float saldo;
struct fecha ultimo_pago;
};
struct fecha fecha1 = {1, 10, 2001};
struct tarjetas cliente1 = {34231,
‘A’, “Pedro García”, 3200.0,
{12, 3, 1993}};
struct tarjetas clientes[100] =
{
3250, ‘A’, “Pedro Sánchez”,
25000.56, {23, 3, 1997},
3251, ‘C’, “Angel Molina”,
27025.36, {5, 24, 1997}
};
9
Ejemplo
struct
{
char nombre[100];
unsigned int cod_ciudad; /* código */
int cod_provincia;
unsigned int cod_postal; /* hasta 65535*/
unsigned long int num_habitantes;
} poblacion = {“Valencia”, 35634, 46, 10056, 256789};
8. Acceso a los miembros de
una estructura
variable_estructura.miembro [.miembro]
struct fecha
{
cliente1.num_tarjeta = 44444;
int dia;
int mes;
printf(“Nombre: %s\n”, cliente2.nombre);
int año;
};
cliente1.saldo = cliente1.saldo + 10000;
struct tarjetas
{
long int num_tarjeta; cliente1.ultimo_pago.dia = 6;
char tipo_cuenta;
mis_clientes[25].ultimo_pago.mes = 12;
char nombre[80];
float saldo;
struct fecha ultimo_pago;
} cliente1, cliente2, mis_clientes[100];
10
9. Operaciones sobre
estructuras
z
Lectura/escritura de estructuras: miembro a
miembro.
z
Asignación de estructuras: directa, siempre
que sean exactamente del mismo tipo.
Ejemplo:
struct cliente cliente1, cliente2;
cliente1 = cliente2;
10. Estructuras como
parámetros
z
Miembros de
parámetro.
una
z
Usar una
retorno.
z
Paso de estructuras por referencia.
estructura
estructura
como
como
valor
de
11
Pasar como parámetro un
miembro de la estructura
float incremento (float saldo, int mes)
{
if (mes<=6) return 0.05*saldo;
else
return 0.0;
}
Incremento de saldo en un 5%
para los pagos del primer
void main()
semestre
{
int i;
struct tarjetas cliente[N];
for (i=0; i<N; i++)
cliente[i].saldo += incremento (cliente[i].saldo,
cliente[i].ultimo_pago.mes);
}
void incremento (float *saldo, float incremento)
{
*saldo = *saldo + incremento;
}
Incremento de saldo en la
cantidad pasada como parámetro
(el saldo se pasa por referencia)
void main()
{
int i;
struct tarjetas cliente[N];
for (i=0; i<N; i++)
incremento (&(cliente[i].saldo), 300.6);
}
12
Una estructura como valor de
retorno
struct tarjetas crear_tarjeta ()
{
struct tarjetas cli;
printf(“Número de tarjeta: ”);
scanf(“%ld”, &cli.num_tarjeta);
printf(“Tipo de tarjeta (A/C): ”);
scanf(“%c”, &cli.tipo_cuenta);
printf(“Nombre del cliente: ”);
gets(cli.nombre);
printf(“Saldo inicial de la tarjeta: ”); scanf(“%f”, &cli.saldo);
return cli;
}
void main()
{
Llenar los datos de las tarjetas
int i;
struct tarjetas cliente[N];
for (i=0; i<N; i++)
cliente[i] = crear_tarjeta();
}
Otra versión
struct tarjetas crear_tarjeta (struct tarjetas cli)
{
printf(“Número de tarjeta: ”);
scanf(“%ld”, &cli.num_tarjeta);
printf(“Tipo de tarjeta (A/C): ”);
scanf(“%c”, &cli.tipo_cuenta);
printf(“Nombre del cliente: ”);
gets(cli.nombre);
printf(“Saldo inicial de la tarjeta: ”); scanf(“%f”, &cli.saldo);
return cli;
}
void main()
{
int i;
struct tarjetas cliente[N];
for (i=0; i<N; i++)
cliente[i] = crear_tarjeta(cliente[i]);
}
13
Pase por referencia
Cuando se pasa una estructura como un
parámetro por referencia, para acceder a los
miembros de la estructura dentro de la función,
en lugar de usar un punto se usa una flecha
(signo menos seguido de signo mayor).
Acceso a los miembros de las estructuras en la
función:
punteroÆmiembro
void modificar_tarjeta (tarjeta *cli)
{
printf(“Nuevo número de tarjeta: ”);
printf(“Nuevo tipo de tarjeta (A/C): ”);
printf(“Nuevo nombre del cliente: ”);
printf(“Saldo inicial de la tarjeta: ”);
}
void main()
{
int i;
tarjetas cliente[N];
for (i=0; i<N; i++)
modificar_tarjeta(&cliente[i]);
}
scanf(“%ld”, &cliÆnum_tarjeta);
scanf(“%c”, &cliÆtipo_cuenta);
gets(cliÆnombre);
scanf(“%f”, &cliÆsaldo);
Modificar los datos de las
tarjetas
14
Otra sintaxis
void modificar_tarjeta (tarjeta *cli)
{
printf(“Nuevo número de tarjeta: ”);
&(*cli).num_tarjeta);
printf(“Nuevo tipo de tarjeta (A/C): ”);
printf(“Nuevo nombre del cliente: ”);
printf(“Saldo inicial de la tarjeta: ”);
}
scanf(“%ld”,
scanf(“%c”, &*(cli).tipo_cuenta);
gets((*cli).nombre);
scanf(“%f”, (*cli).saldo);
void main()
{
int i;
tarjetas cliente[N];
for (i=0; i<N; i++)
modificar_tarjeta(&cliente[i]);
}
Ejercicio
La UPV está renovando su programa
informático de gestión de alumnos. Para cada
alumno desea almacenar sus datos personales
y su expediente académico.
Escribir un programa que obtenga los datos de
los 35.000 alumnos de la UPV
15
Escribir dos funciones:
z
Lee: lee los datos de todos los alumnos de la
upv (para cada alumno lee todas sus notas).
z
Escribe: escribe los datos de un único alumno
de la universidad.
#define N 35000
#define NUM_NOTAS 100
struct alumno
{
char nombre[80];
unsigned long int dni;
float notas[NUM_NOTAS ];
};
16
void lee (struct alumno a[N])
{
int i, j;
for (i=0; i<N; i++)
{
printf(“Nombre: “);
gets(a[i].nombre);
printf(“Dni: “);
scanf(“%ld”, &a[i].dni);
for (j=0; j<NUM_NOTAS; j++)
{
printf(“Nota de la asignatura %d: “);
scanf(“%f”,&a[i].notas[j]);
}
}
}
void escribe (struct alumno al)
{
int j;
printf(“Nombre: %s\n”, al.nombre);
printf(“Dni: %ld”, al.dni);
for (j=0; j<NUM_NOTAS; j++)
printf(“Nota de la asignatura %d: %f”, j,
al.notas[j]);
}
17
void main ()
{
struct alumno a[N];
int i;
lee (a);
for (i=0; i<N; i++)
escribe (a[i]);
}
Ejercicio
Una ONG decide diseñar un programa que le ayude a
gestionar las distintas donaciones que recibe, dado
que es una ONG de reciente creación, esta sólo tiene
10 proyectos de acción en curso.
La información que guarda de cada proyecto de
acción es la siguiente:
z
z
z
z
Nombre de la persona responsable.
Nombre del proyecto (cadena de caracteres).
Cantidad presupuestada para realizar el proyecto.
Cantidad recaudada por el momento para este proyecto
(número real) y número de donaciones (entero).
18
Diseñar un programa en C que aporte las siguientes funciones (menú de
opciones):
z
z
z
z
Introducción de los datos iniciales: El programa solicitará los datos de
los 10 proyectos iniciales.
Donación de una cantidad: El programa solicitará el nombre del proyecto
y la cantidad que se desea donar. Si todavía no se ha cubierto el
presupuesto en su totalidad, se considerará la donación aunque esto
provoque que se supere la cantidad presupuestada, en cuyo caso el
proyecto dispone de un superhabit inicial. Si el presupuesto de ese
proyecto ya había sido cubierto, se destinará este dinero al proyecto no
cubierto con mayor diferencia entre las cantidades presupuestada y
recaudada, y se avisará que la cantidad se ha destinado a otro proyecto
indicando el nombre.
Listado de los proyectos no cubiertos: Mostrará por pantalla los datos
de los proyectos cuyo presupuesto no ha sido cubierto todavía.
Salir: Escogida esta opción el programa finalizará.
#include <stdio.h>
#include <string.h>
#define TRUE 1
#define FALSE 0
#define N 10 /* Número de proyectos */
struct proyecto
{
char nombre_responsable[50];
char nombre_proyecto[50];
float presupuesto;
float recaudado;
int numero_donaciones;
};
El tipo se declara como
global para que puedan
utilizarlo todas las
funciones
19
/* Menú general */
int menu ()
{
int c;
do
{
printf("1. Introducir datos iniciales\n");
printf("2. Donación\n");
printf("3. Listado de proyectos no cubiertos\n");
printf("4. Salir\n");
printf("Opción: "); scanf("%d",&c);
if ((c<1) || (c>4)) printf("Opción Incorrecta\n");
}
while ((c<1) || (c>4));
return c;
}
/* Introducción de los datos iniciales de los proyectos */
void introducir_datos (struct proyecto proyectos[N])
{
int i;
for (i=0; i<N; i++)
{
printf("Proyecto %d\n", i+1);
printf("Responsable: ");
gets(proyectos[i].nombre_responsable);
printf("Proyecto: ");
gets(proyectos[i].nombre_proyecto);
printf("Presupuesto: ");
scanf("%f", &proyectos[i].presupuesto);
printf("Recaudado hasta el momento: ");
scanf("%f", &proyectos[i].recaudado);
printf("Número de donaciones: ");
scanf("%d", &proyectos[i].numero_donaciones);
}
}
20
/* Listado de los proyectos cuyo presupuesto no ha sido cubierto
todavía */
void listado (struct proyecto proyectos[N])
{
int i;
for (i=0; i<N; i++)
if (proyectos[i].presupuesto > proyectos[i].recaudado)
{
printf("Proyecto %d\n", i+1);
printf("Responsable: %s\n",
proyectos[i].nombre_responsable);
printf(“Nombre del proyecto: %s\n",
proyectos[i].nombre_proyecto);
printf("Presupuesto: %.2f\n",
proyectos[i].presupuesto);
printf("Recaudado hasta el momento: %.2f\n",
proyectos[i].recaudado);
printf("Número de donaciones: %d\n",
proyectos[i].numero_donaciones);
}
}
/* Donación de una cantidad */
void donacion (struct proyecto proyectos[N])
{
char nombre_proyecto[50];
float donacion, diferencia, mayor_diferencia=0;
int i=0, j, encontrado=FALSE, nuevo;
printf("Nombre del proyecto: ");
gets(nombre_proyecto);
while ((i<N) && encontrado==FALSE)
if (strcmp(proyectos[i].nombre_proyecto,
nombre_proyecto) == 0)
encontrado = TRUE;
else i++;
21
if (encontrado==TRUE)
{
printf("Cantidad a donar: ");
scanf("%f", &donacion);
if (proyectos[i].recaudado<proyectos[i].presupuesto)
{ /* Se añade al proyecto la cantidad donada */
proyectos[i].recaudado += donacion;
proyectos[i].numero_donaciones++;
}
else
{ /* La donación se destina a otro proyecto */
nuevo=-1;
for (j=0; j<N; j++)
{ /* Hayar el máximo de la diferencia */
diferencia = proyectos[j].presupuesto - proyectos[j].recaudado;
if ((diferencia>mayor_diferencia) && (diferencia>0))
{
mayor_diferencia = diferencia;
nuevo = j;
}
}
/* Nuevo es el proyecto con mayor diferencia entre recaudado y
presupuestado. Si nuevo es –1 significa que no hay ningún proyecto que
cumpla las condiciones y no se hará la donación */
if (nuevo>0)
{
printf("La donación se destina al proyecto %s\n",
proyectos[nuevo].nombre_proyecto);
proyectos[nuevo].recaudado += donacion;
proyectos[nuevo].numero_donaciones++;
}
else
printf("No es posible hacer donaciones\n");
}
}
else
/* No se ha encontrado un proyecto con el nombre indicado */
printf("Proyecto no existe\n");
}
22
void main() /* Programa Principal */
{
struct proyecto proyectos[N];
int opc;
do
{
opc = menu ();
switch(opc)
{
case 1: introducir_datos (proyectos); break;
case 2: donacion (proyectos);
break;
case 3: listado (proyectos);
break;
}
}
while (opc != 4);
}
Ejercicio
En la secretaría general de la UPV se han realizado las preinscripciones
para cada uno de los centros (escuelas y facultades).
Para realizar la preinscripción la secretaría rellena los siguientes datos
para cada uno de los alumnos:
z
z
z
Nombre.
Dni.
Código del centro al que se preinscribe. El centro al que se inscribe está
codificado (1-EUITI, 2-ETSII,...).
La secretaría envía los datos almacenados de las preinscripciones a cada
uno de los centros (los mismos datos a todos los centros) para obtener los
datos de los alumnos matriculados. Los centros seleccionan los datos de
los alumnos preinscritos a su centro, añadiendo además el nombre de la
titulación y el de la especialidad a la que están preinscritos. Estos datos se
rellenan a partir de los sobres de matrícula que entregan los alumnos.
23
Implementar un programa que solicite los datos de la
preinscripción.
Después debe solicitar el código del centro del que se
desean seleccionar los datos y tome los datos de la
preinscripción a dicho centro, rellene los datos que
faltan y saque un listado con nombre, dni, titulación y
especialidad de cada alumno preinscrito.
El número máximo de alumnos
preinscribirse en la UPV es de 50.000.
que
pueden
#include <stdio.h>
#include <string.h>
#define ALUMNOS 50000
/* Tipo de datos de un alumno preinscrito */
typedef struct
{
char nombre[50];
char dni[10];
int centro;
} alumno_preinscrito;
/* Datos de un alumno matriculado en un centro en concreto */
typedef struct
{
char nombre[50];
char dni[10];
char titulacion[50];
char especialidad[50];
} alumno_matriculado;
24
/* Solicita los datos de la preinscripción: solicita al usuario
los datos para rellenar el vector de alumnos preinscritos
en la UPV. */
void rellena_preinscripcion (alumno_preinscrito p[ ])
{
int i;
for (i=0; i<ALUMNOS; i++)
{
printf("Nombre del alumno: ");
gets(p[i].nombre);
printf("DNI: ");
scanf("%s",p[i].dni);
printf("Código del centro: ");
scanf("%d",&p[i].centro);
}
}
/* Obtiene los datos del centro */
int obten_datos (alumno_preinscrito p[ ],
alumno_matriculado m[ ], int codigo)
{
int i, j=0;
for (i=0; i<ALUMNOS; i++)
if (p[i].centro==codigo)
{
/* Copia los datos de la preinscripción en la matrícula */
strcpy(m[j].nombre, p[i].nombre);
strcpy(m[j].dni, p[i].dni);
/* Solicita los datos que faltan */
printf("Titulación: "); gets(m[j].titulacion);
printf("Especialidad: "); gets(m[j].especialidad);
j++;
}
return j; /* Nº de alumnos matriculados para el listado */
}
25
/* Listado */
void listado(alumno_matriculado m[ ], int n,
int codigo)
{
int i;
printf("Listado de alumnos del centro %d\n",
codigo);
for (i=0; i<n; i++)
printf("%s %s %s %s\n",m[i].nombre,
m[i].dni,
m[i].titulacion, m[i].especialidad);
}
void main()
{
alumno_preinscrito preinscripcion[ALUMNOS];
alumno_matriculado matricula_centro[ALUMNOS];
int codigo, matriculados;
/* Solicita los datos de la preinscripción */
rellena_preinscripcion(preinscripcion);
/* Obtiene los datos del centro */
printf("Introduzca el código del centro: ");
scanf("%d",&codigo);
matriculados = obten_datos (preinscripcion, matricula_centro,
codigo);
/* Listado */
listado(matricula_centro, matriculados, codigo);
}
26
Descargar