introducción a la programación 1 práctica 7: estructuras

Anuncio
INTRODUCCIÓN A LA PROGRAMACIÓN 1
PRÁCTICA 7: ESTRUCTURAS
TRANSFORMACIÓN DE LEA A C
LEA
C
DEFINICIÓN DE UN REGISTRO (ESTRUCTURA)
typedef struct
{
T1 c1;
T2 c2;
...
Tn cn;
} Tr;
Tipos
Tr: registro
cl: T1
c2: T2
...
cn: Tn
fregistro
typedef Tr * PTr;
variables
r: Tr
Tr r;
PTr pr;
Tr r={v1, v2, ..., vn};
Typedef struct
{
Cadena nombre, apellido1, apellido2;
int edad;
long dni;
char sexo;
} Tpersona;
tipos
Tpersona: registro
nombre, apellido1, apellido2: cadena
edad, dni: entero
sexo: caracter
fregistro
variables
empleado: Tpersona
Tpersona empleado;
Tpersona empleado={"Alicia", "Gómez", "Cruz",
21, 12345678, 'm'};
ACCESO A LOS CAMPOS DE UN REGISTRO
r.ci
r.ci (acceso a través de una variable estructura)
pr->ci (acceso a través de un puntero a estructura)
empleado.nombre := "Alicia"
escribir empleado.edad
strcpy (empleado.nombre, "Alicia");
printf ("%d", empleado.edad);
TABLAS DE REGISTROS
tipos
Ttabla: tabla [dim] de Tr
variables
nombre: Ttabla
typedef Tr Ttabla[dim];
constantes
N: 200
tipos
Ttpersona: tabla [N] de Tpersona
variables
clase: Ttpersona
#define N 200
Acceso a un elemento de la tabla:
elemento i-ésimo: clase[i]
nombre del elemento i-ésimo: clase[i].nombre
Acceso a un elemento de la tabla:
Elemento i-ésimo: clase[i-1]
nombre del elemento i-ésimo: clase[i-1].nombre
Ttabla nombre;
typedef Tpersona Ttpersona[N];
Ttpersona clase;
Práctica 7: Estructuras
2
LEA
C
PASO DE REGISTROS COMO PARÁMETROS
a) El registro es un parámetro de entrada:
a) El registro es un parámetro de entrada:
Llamada:
empleado: Tpersona
escribe_datos_empleado (empleado)
Prototipo:
void escribe_datos_empleado (Tpersona);
Definición:
proc escribe_datos_empleado (ent e: Tpersona)
prin
escribir e.nombre, e.apellido1, e.apellido2
escribir e.edad, e.dni, e.sexo
fin
Llamada:
Tpersona empleado;
escribe_datos_empleado (empleado);
Definición:
void escribe_datos_empleado (Tpersona e)
{
printf ("%s %s, %s\n", e.nombre, e.apellido1,
e.apellido2);
printf ("%ld %ld %c", e.edad, e.dni, e.sexo);
}
b) El registro es un parámetro de salida:
b) El registro es un parámetro de salida:
Llamada:
empleado: Tpersona
lee_datos_empleado (empleado)
Prototipo:
typedef Tpersona * PTpersona;
void lee_datos_empleado (PTpersona);
Definición:
proc lee_datos_empleado (sal e: Tpersona)
prin
leer e.nombre, e.apellido1, e.apellido2
leer e.edad, e.dni, e.sexo
fin
Llamada:
Tpersona empleado;
lee_datos_empleado (&empleado);
Definición:
void lee_datos_empleado (PTpersona e)
{
gets (e->nombre);
gets (e->apellido1);
gets (e->apellido2);
scanf ("%ld%ld%c", &e->edad, &e->dni,
&e->sexo);
}
Práctica 7: Estructuras
EXPERIMENTOS
E.7.1
En el siguiente programa se definen dos estructuras, una para almacenar una fecha y otra para
almacenar el nombre y la fecha de nacimiento de una persona, de forma que para la fecha de
nacimiento se hace uso de la estructura anterior. La definición de estas estructuras es la siguiente:
typedef struct
{
int dia;
int mes;
int anio;
} Fecha;
typedef struct
{
Cadena nombre;
Fecha nacimiento;
} Persona;
Además, hemos definido un procedimiento (no devuelve nada) que dada una persona nos imprime sus
datos por pantalla con el siguiente prototipo:
void escribe(Persona);
Complete el siguiente programa para que funcione de manera correcta:
#include <stdio.h>
#include "f:\asigna\ip1\public\lea.h"
typedef struct
{
int dia;
int mes;
int anio;
} Fecha;
typedef struct
{
Cadena nombre;
Fecha nacimiento;
} Persona;
void escribe(Persona);
void main (void)
{
Persona empleado;
printf("\nDame el nombre: ");
scanf("%s",_____);
printf("\nDame la fecha de nacimiento: ");
scanf("%d%d%d",_____,_____,_____);
escribe(empleado);
}
void escribe(Persona per)
{
printf("\nEl nombre es: %s ",_____);
printf("\nNació el: %d/%d/%d",_____,_____,_____);
}
3
Práctica 7: Estructuras
4
E.7.2 En el siguiente programa se define un nuevo tipo Cadena que denominamos Cadena2 basado en
una estructura y se implementa un procedimiento para concatenar dos cadenas. Este procedimiento
tiene el prototipo:
void concatena (PCadena2 cad1, Cadena2 cad2);
y concatena la cadena cad2 a la cadena cad1, devolviendo como parámetro de E/S la propia cadena cad1.
Complete el código para que el programa realice su tarea.
#include <stdio.h>
#include "f:\asigna\ip1\public\lea.h"
typedef struct
{
Cadena texto;
int longitud;
} Cadena2;
typedef Cadena2* PCadena2;
void concatena (PCadena2, Cadena2);
void main (void)
{
Cadena2 c1={"hola",4}, c2={"adios",5};
concatena (&c1, c2);
printf ("\nCadena 1.
c1.longitud);
printf ("\nCadena 2.
c2.longitud);
Texto=
%10s,
Longitud=
%3d",
c1.texto,
Texto=
%10s,
Longitud=
%3d",
c2.texto,
}
void concatena (PCadena2 p, Cadena2 c)
{
p->longitud = __________ + __________;
strcat (__________, __________);
}
El resultado en pantalla debe ser el siguiente:
Cadena 1. Texto=
Cadena 2. Texto=
holaadios, Longitud=
adios, Longitud=
9
5
E.7.3 El siguiente programa crea una tabla de registros con una serie de números y sus respectivos
factoriales. Complete el código para que el programa funcione correctamente. Utilice la función
factorial que desarrolló en una práctica anterior (disponible también en la biblioteca
f:\asigna\ip1\public\mates.lib).
#include <stdio.h>
#include <assert.h>
#include "f:\asigna\ip1\public\mates.h"
#define MAX 20
typedef struct
{
int num;
long fac;
} RFac;
typedef RFac TRFac[MAX];
int rellenatabla (TRFac);
void muestratabla (const TRFac, int);
void main (void)
{
TRFac tablafac;
Práctica 7: Estructuras
int n;
n = rellenatabla (tablafac);
muestratabla (tablafac, n);
}
int rellenatabla (TRFac t)
{
int i, tam;
printf ("\n¿Cuántos factoriales desea calcular? ");
scanf ("%d", &tam);
assert (tam <= MAX);
for (i=0; i<tam; i++)
{
__________=i+1;
__________=factorial(i+1);
}
return tam;
}
void muestratabla (const TRFac t, int m)
{
int i;
assert (m
for (i=0;
{
printf
printf
}
}
<= MAX);
i<m; i++)
("\nNúmero: %3d ", __________);
(". Factorial: %ld", __________);
5
Práctica 7: Estructuras
EJERCICIOS DE SINTAXIS PROPUESTOS
S.7.1
·
·
·
·
S.7.2
·
·
·
Declare las siguientes variables estructura:
Una variable hora_inicio de tipo Hora.
Una variable america de tipo Fecha con valor inicial igual a la fecha del descubrimiento de
América.
Una tabla empleados capaz de almacenar 200 elementos de tipo Persona.
Una tabla directorio capaz de almacenar 256 elementos de tipo EntradaDir.
Una variable p_persona de tipo puntero a Persona.
·
·
·
·
·
A partir de las declaraciones del ejercicio anterior, escriba las expresiones para
El año en que se descubrió América.
El nombre del empleado i-ésimo de la tabla empleados.
El día de nacimiento del empleado i-ésimo de la tabla empleados.
El nombre de la persona a la que apunta p_persona.
El día de nacimiento de la persona a la que apunta p_persona.
·
·
S.7.3
S.7.4
Defina los siguientes tipos de estructuras:
Un tipo estructura Hora con tres campos enteros hora, minutos, segundos.
Un tipo estructura Fecha con tres campos enteros dia, mes, anyo.
Un tipo estructura Persona con los siguientes campos:
·
nombre: cadena de 20 caracteres.
·
apellidos: cadena de 40 caracteres.
·
dni: entero largo.
·
fecha_nacimiento: estructura de tipo Fecha.
Un tipo estructura EntradaDir con los siguientes campos:
·
nombre: cadena de 8 caracteres.
·
extension: cadena de 3 caracteres.
·
tamanyo: entero largo.
·
fecha_creacion: estructura de tipo Fecha.
·
hora_creacion: estructura de tipo Hora.
Un número complejo se puede representar mediante la siguiente estructura:
typedef struct
{
double a, b;
} Complejo;
Escriba las siguientes funciones de manipulación de números complejos:
void escribe_complejo (Complejo c);
Escribe un dato de tipo complejo.
Complejo lee_complejo (void);
Lee un dato de tipo complejo.
Complejo suma_complejos (Complejo c1, Complejo c2);
Suma dos datos de tipo complejo.
Complejo multiplica_complejos (Complejo c1, Complejo c2);
Multiplica dos datos de tipo complejo.
S.7.5
Utilizando las funciones del ejercicio anterior, escriba un programa que lea dos datos de tipo
Complejo y calcule e imprima la suma y el producto de ambos.
S.7.6
Reescriba las funciones del ejercicio S.7.4 para que tengan los siguientes prototipos:
void lee_complejo (PComplejo c);
void suma_complejos (Complejo c1, Complejo c2, PComplejo c);
void multiplica_complejos (Complejo c1, Complejo c2, PComplejo c);
siendo PComplejo el tipo definido de la siguiente forma:
6
Práctica 7: Estructuras
typedef Complejo * PComplejo;
S.7.7
Sea la siguiente definición de estructura:
typedef struct
{
int dia, mes, anyo;
int dia_del_anyo;
} Fecha;
La función
void dias_transcurridos (PFecha pf);
recibe como parámetro un puntero a una estructura de tipo Fecha que contiene un día, mes y año, y calcula
el valor del campo dia_del_anyo, que es igual al número de días transcurridos desde el comienzo
del año. Complete la función para que realice su cometido.
void dias_transcurridos (PFecha pf)
{
int i, bisiesto, dias;
int tabla_dias[2][13] =
{{0,31,28,31,30,31,30,31,31,30,31,30,31},
{0,31,29,31,30,31,30,31,31,30,31,30,31}};
dias = ??????????;
bisiesto = pf->anyo%4==0 && pf->anyo%100!=0 || pf->anyo%400==0;
for (i=1; i<??????????; i++)
dias = dias + tabla_dias[bisiesto][i];
?????????? = dias;
}
S.7.8
La siguiente función lee una fecha del teclado y la devuelve como resultado. Complete el código de
la función.
Fecha lee_fecha (void)
{
Fecha f;
printf ("\nIntroduzca el día (1-31): ");
scanf ("%d", ??????????);
while (??????????<1 || ??????????>31)
scanf ("%d", ??????????);
printf ("\nIntroduzca el mes (1-12): ");
scanf ("%d", ??????????);
while (??????????<1 || ??????????>12)
scanf ("%d", ??????????);
printf ("\nIntroduzca el año: ");
scanf ("%d", ??????????);
dias_transcurridos (??????????); /* Calcular el día del año */
return f;
}
S.7.9
La siguiente función lee una fecha del teclado y la devuelve a través de una variable de salida.
Complete el código de la función.
void lee_fecha (PFecha pf)
{
printf ("\nIntroduzca el día (1-31): ");
scanf ("%d", ??????????);
while (??????????<1 || ??????????>31)
scanf ("%d", ??????????);
7
Práctica 7: Estructuras
8
printf ("\nIntroduzca el mes (1-12): ");
scanf ("%d", ??????????);
while (??????????<1 || ??????????>12)
scanf ("%d", ??????????);
printf ("\nIntroduzca el año: ");
scanf ("%d", ??????????);
dias_transcurridos (??????????); /* Calcular el día del año */
}
S.7.10 Utilizando la siguiente estructura definida para representar números complejos
typedef struct
{
double a, b;
/* forma binómica */
double mod, alfa; /* forma polar */
} Complejo;
typedef Complejo * PComplejo;
escriba una función que, dado un número complejo en forma binómica, calcule las correspondientes
coordenadas en forma polar. El prototipo es:
void binomica_a_polar (PComplejo c);
y la fórmula de conversión es la siguiente:
mod = a 2 + b2
b
alfa = arctg
a
S.7.11
Sea el siguiente algoritmo (con sus definiciones de tipos correspondientes):
typedef struct
{
Cadena nombre;
int golf, golc, puntos;
} Nodo;
void imprime_clasificacion (const Nodo equipos[], const int orden[],
int neq)
{
int i, puntos_ant=-1, dif, puntos;
char c;
printf ("\nCLASIFICACIÓN GENERAL");
printf ("\n==============================");
printf ("\nNOMBRE
PUNTOS DIF");
printf ("\n==============================");
for(i=0; i<neq; i++)
{
puntos = equipos[orden[i]].puntos;
dif = equipos[orden[i]].golf - equipos[orden[i]].golc;
if (puntos != puntos_ant)
{
printf ("\n%-20s%5d", equipos[orden[i]].nombre, puntos);
puntos_ant = puntos;
}
else
printf ("\n%-20s%5c", equipos[orden[i]].nombre, '-');
if (dif>0)
c = '+';
Práctica 7: Estructuras
else if (dif<0)
c = '-';
else
c=´’ ’;
printf ("%3c%2d", c, abs(dif));
}
printf ("\n==============================");
}
y sean las siguientes tablas de datos:
Nodo equipos[MAX]={{"SEVILLA F.C.",59,33,42},{"REAL BETIS",52,25,45},
{"DPVO CORUÑA",60,34,49},{"REAL MADRID",90,28,55},
{"REAL ZARAGOZA",52,52,42},{"F.C. BARCELONA",86,42,45},
{"R.C.D. ESPAÑOL", 58, 45, 42}};
int orden[MAX] = {3, 2, 1, 5, 0, 4, 6};
Siga la traza del algoritmo cuando se realiza la llamada
imprime_clasificacion (equipos, orden, 7);
indicando el resultado impreso por la función.
NOTAS:
a) La función abs devuelve el valor absoluto de un entero.
b) En el resultado impreso debe quedar claro el número de espacios en blanco existentes entre cada
uno de los datos que se imprimen.
S.7.12
El siguiente programa lee desde la entrada estándar el nombre y los puntos de los 22 equipos de
una liga de fútbol. Los nombres tienen un máximo de 22 caracteres. Corrija, justificadamente, los
errores del programa.
#include <stdio.h>
#define MAX 22;
typedef char Nombre[MAX];
typedef strutc
{
char Nombre;
int puntos;
} Equipo;
void main (void)
{
Equipo liga[];
for (i=0; i<=MAX; i++)
scanf ("%s%d", liga[i].NOMBRE, liga[i].puntos);
}
EJERCICIOS DE ALGORÍTMICA PROPUESTOS
A.7.1
Sean las siguientes definiciones:
#define MAXCAR 31
#define MAX 10
typedef char Cadena[MAXCAR];
typedef struct
{
Cadena nombre, apellido1, apellido2;
int edad;
long dni;
char sexo;
} Persona;
typedef Persona TPersona[MAX];
9
Práctica 7: Estructuras
Escriba una función
int busca_persona (const TPersona clase, int npersonas, long dni);
que busque de manera secuencial en la tabla clase aquella persona cuyo DNI coincida con el valor
especificado en el parámetro dni. La función devolverá la posición de la persona, si la encuentra, o
un valor -1 en caso contrario.
A.7.2
Modifique la función anterior para que utilice el esquema de búsqueda binaria.
A.7.3
Basándose en la misma definición de Persona del ejercicio anterior, escriba una función
void ordena_personas (TPersona clase, int npersonas);
que ordene la tabla clase en orden ascendente del campo edad.
A.7.4
Una tabla de búsqueda (lookup table) es una tabla de estructuras en la que se realiza una búsqueda
por uno de sus campos y se obtiene el valor almacenado en otro campo. Por ejemplo, para
almacenar los valores de las variables de un programa se puede utilizar una tabla como la siguiente:
#define MAX_SIMBOLOS 100
typedef struct
{
Cadena identificador;
int valor;
} Simbolo;
Simbolo tabla_simbolos[MAX_SIMBOLOS];
Escriba una función de búsqueda, que, dado un identificador, obtenga el valor que le corresponde en la
tabla. Su prototipo será el siguiente:
int buscaValor (const Simbolo tabsim[], int nsim, Cadena ident);
siendo nsim el número de identificadores almacenados en la tabla tabsim.
A.7.5
Sean las siguientes definiciones y declaraciones:
typedef char Cadena[MAXCAR];
typedef struct
{
int cod_idioma;
Cadena mensajes[NMENSAJES];
} Mens;
Mens tabla_idiomas[NIDIOMAS];
Escriba una función
void muestra_mensaje (const Mens tabla_idiomas[], int codigo_idioma,
int numero_mensaje);
que reciba como parámetro un código de idioma y un número de mensaje (entre 1 y NMENSAJES) e
imprima el mensaje correspondiente de tabla_idiomas.
A.7.6
Sean las siguientes definiciones y declaraciones:
typedef struct
{
int opcion; /* número de la opción */
Cadena mensaje; /* mensaje de la opción */
int visible; /*visibilidad de la opción: 1=visible, 2=no visible*/
} Opcion;
Opcion tabla_menu[MAX];
10
Práctica 7: Estructuras
11
Escriba una función
void menu (const Opcion tabla_menu[], int n);
que reciba como parámetros una tabla que representa un menú de opciones y un entero que indica el
número de elementos de dicha tabla, e imprima el menú correspondiente, teniendo en cuenta que
sólo se mostrarán en la pantalla aquellas opciones del menú que tengan activado el indicador de
visibilidad.
A.7.7
Se dispone de una tabla bidimensional de estructuras que contiene datos relativos al padrón de
habitantes de una ciudad. Las filas representan los distritos de la ciudad (en concreto 10) y las
columnas los años en que se han realizado padrones (1981, 1986, 1991 y 1996).
1981
1986
1991
1996
distrito 1
distrito 2
...
distrito 10
Cada elemento de la tabla es una estructura que contiene el número de hombres y de mujeres de cada
distrito en el padrón de cada año. Un tercer campo indica la tendencia de crecimiento del distrito,
pudiendo tener tres valores posibles: '+' si la población total del distrito ha crecido con respecto al
padrón anterior, '-' si ha decrecido e '=' si se mantiene estable.
hombres
mujeres
crecimiento
La tabla está rellena a excepción de la tendencia de crecimiento, que sólo se conoce para el año 1981. Se
pide escribir un programa que:
a) Calcule las tendencias de crecimiento de cada distrito para el resto de los años.
b) Muestre tres listados con los distritos que durante los cuatro años han mantenido una tendencia de
crecimiento positiva, negativa y estable, respectivamente.
A.7.8
Se dispone de una estructura de datos que representa las cartas de la baraja española:
#define TAM 40
#define MAXCAR 8
typedef char Cadena[MAXCAR];
typedef struct
{
Cadena palo;
int valor;
} Carta;
typedef Carta Baraja[TAM];
Cada carta tiene un palo y un valor. Existen cuatro palos: oros, copas, espadas y bastos. Por su parte, los
valores posibles son 1, 2, 3, 4, 5, 6, 7, 10, 11 y 12.
Realice una función que reciba un número variable de cartas de la baraja, desordenadas, y las devuelva
ordenadas según los siguientes criterios:
1. Los palos seguirán el orden oros, copas, espadas, bastos.
2. Dentro de cada palo se seguirá el orden ascendente del valor.
El prototipo de la función es:
Práctica 7: Estructuras
12
void ordena_baraja (Baraja b, int ncartas);
Ejemplo: si b contiene las cartas
{"bastos",10}, {"oros",5}, {"copas",7}, {"oros",3}, {"copas",1}
al aplicar la función quedará ordenada de la siguiente forma:
{"oros",3}, {"oros",5}, {"copas",1}, {"copas",7}, {"bastos",10}
A.7.9
Escriba una función
void tenis (Cadena est_anterior, Cadena est_nuevo, int ult_punto);
capaz de calcular el estado de un juego en un partido de tenis, tomando como datos de entrada el estado
anterior del juego y el resultado del último punto disputado. Tanto el estado anterior como el nuevo
estado son cadenas de caracteres, y sus posibles valores se muestran en la tabla. El resultado del
último punto es un número cuyo valor puede ser 1 ó 2, según el último punto disputado haya sido
ganado por el jugador que sirve (jugador 1) o el que resta (jugador 2), respectivamente. La
evolución de los puntos en un juego de un partido de tenis es la siguiente:
ESTADO ANTERIOR
DEL JUEGO
NUEVO ESTADO
GANA JUGADOR 1
GANA JUGADOR 2
0-0
15-0
0-15
15-0
30-0
15-15
0-15
15-15
0-30
15-15
30-15
15-30
30-0
40-0
30-15
0-30
15-30
0-40
30-15
40-15
30-30
15-30
30-30
15-40
30-30
40-30
30-40
40-0
JUEGO-1
40-15
0-40
15-40
JUEGO-2
40-15
JUEGO-1
40-30
15-40
30-40
JUEGO-2
40-30
JUEGO-1
IGUALES
30-40
IGUALES
JUEGO-2
IGUALES
VENTAJA-1
VENTAJA-2
VENTAJA-1
JUEGO-1
IGUALES
VENTAJA-2
IGUALES
JUEGO-2
A.7.10 Si sabemos a priori el número máximo de elementos que tiene una secuencia, podemos
implementarla mediante una tabla de registros. Cada registro de la tabla estará compuesto por dos
Práctica 7: Estructuras
13
campos, que contienen el valor del elemento de la secuencia y la posición en la tabla del siguiente
elemento de la secuencia. Por ejemplo, la secuencia de enteros positivos (máximo 4 elementos)
6, 12, 98
se podría almacenar en una tabla de la siguiente forma:
elemento
valor
siguiente
0
6
3
1
98
-1
2
-1
-1
3
12
1
El último elemento tiene como siguiente el valor -1, y el primer elemento de la secuencia siempre ocupa la
posición 0 de la tabla. Los elementos no ocupados de la tabla tienen un valor -1 en sus dos campos.
Escriba una función en C que permita insertar en orden un entero positivo en una secuencia de enteros
positivos. Utilice las definiciones y el prototipo que se dan a continuación:
#define MAX 100
typedef struct
{
int valor;
int siguiente;
} Elemento;
typedef Elemento Secuencia[MAX];
void insertaElemento (Secuencia s, int elem);
Escriba un programa que lea una secuencia de números enteros positivos del teclado y los vaya insertando
ordenadamente utilizando la función anterior. Posteriormente, el programa mostrará la lista de
números ordenados en la pantalla.
Descargar