Documentos de Académico
Documentos de Profesional
Documentos de Cultura
TEMA 7. Registros
1. Introducción
En la programación de ordenadores el concepto de registro es muy importante. En
múltiples aplicaciones informáticas es necesario establecer una estructura de datos que
agrupe la información de diversos atributos de un único concepto. Un ejemplo habitual
es el concepto de fecha. Programas que manejen fechas son muy habituales en el mundo
real: ingresos de un hospital, informaciones comerciales, gestión de aeropuertos, etc.
¿Qué información debe guardar una fecha? Aunque hay diversas representaciones
posibles, la más elemental es mediante tres enteros que representen el día, el mes y el
año de una fecha. Como los tres datos son de tipo entero, podríamos representar
entonces una fecha como un array para guardar tres enteros. Pero qué ocurre si los datos
que queremos guardar bajo una misma estructura son de distinto tipo. Pensemos por
ejemplo, en la información de un paciente en un sistema de información clínico. ¿Qué
datos se guardan de cada paciente? Como mínimo se necesitarían sus datos personales,
nombre, apellidos y DNI los tres de tipo cadenas de caracteres. Pero sería normal
guardar bajo la denominación de paciente otros datos como edad (entero), sexo
(carácter) o datos clínicos como temperatura corporal (real), presión sanguínea (entero),
etc.
El tipo de datos registro es el que sirve entonces para guardar información de distinto
tipo en una estructura única. Otros ejemplos de datos de tipo registro podrían ser un
vuelo (destino, fecha, número de pasajeros, compañía, etc), un alumno (datos
personales, fecha de nacimiento, asignaturas, notas,…), un vehículo (marca, modelo,
matrícula, fecha de matriculación, …), un medicamento (nombre, precio, fecha de
caducidad, …) etc.
2. Registros en C
struct paciente{
Cadena nombre;
Cadena apellido;
int edad;
char sexo;
float temperatura;
};
Tema 7. Registros
Esto declara struct paciente como un conjunto de campos o atributos. Para definir
variables de tipo paciente se debería poner (en los lugares donde se declaran variables):
typedef struct {
Cadena nombre;
Cadena apellido;
int edad;
char sexo;
float temperatura;
} Paciente;
2.2 Uso de registros. A partir de una variable de tipo struct se pueden acceder a los
atributos que lo conforman usando el operador . (punto) y el nombre del campo. Cada
campo es del tipo que se declaró en el struct. Ejemplo:
1. strcpy(pac1.nombre,"Juan");
2. n=strlen(pac1.apellido);
3. scanf("%d",&pac1.edad);
4. pac1.sexo='H';
5. suma = suma + pac1.temperatura;
2.3. Argumentos de entrada de tipo struct en una función. Un programa tal que
dados dos registros de tipo Paciente calculara la suma de la suma de sus edades
mediante una función sería:
Autor: José C. Riquelme (Universidad de Sevilla)
#include <stdio.h>
#define MAXCAR 256
typedef char Cadena[MAXCAR];
typedef struct {
Cadena nombre;
Cadena apellido;
int edad;
char sexo;
float temperatura;
} Paciente;
En el programa anterior los argumentos reales pac1 y pac2 copian los valores de sus
campos a los argumentos formales p1 y p2 como parámetros de entrada que no van a ser
modificados en la función sumaEdades. Por eso se les pone la clausula const tanto en
la cabecera como en el prototipo.
Otro ejemplo, sería una función tal que dado un registro muestre sus datos en pantalla
en un determinado formato:
Paciente leePaciente(){
Paciente p;
scanf("%c",&p.sexo);
printf("escriba el nombre: ");
scanf("%s",p.nombre);
printf("escriba el apellido: ");
scanf("%s",p.apellido);
printf("escriba la edad: ");
scanf("%d",&p.edad);
printf("escriba la temperatura: ");
scanf("%f",&p.temperatura);
return p;
}
pac1 = leePaciente();
3. El operador . tiene más prioridad que el operador * por eso es necesario poner
paréntesis en la expresión scanf("%d",&(*p).edad);
4. El operador -> tiene más prioridad que el operador & y por eso no hace falta
paréntesis en la expresión scanf("%f",&p->temperatura);
leePaciente(&pac1);
3. Arrays de registros
3.1 Declaración. Como hemos resaltado numerosas veces, la mejor forma de usar un
array es mediante la declaración previa de su tipo con una cláusula typedef. Por
ejemplo:
typedef struct {
Cadena nombre;
Cadena apellido;
int edad;
char sexo;
float temperatura;
} Paciente;
3.2 Uso de los arrays de registros. Para usar un array de struct hay que mezclar el uso
de los arrays con el uso de los campos de un struct.
Por ejemplo si definimos una variable usp de tipo Hospital, usp[3] es un dato de tipo
Paciente y usp[3].nombre es un dato de tipo Cadena que contiene el nombre del
paciente que ocupa la cuarta posición del array.
Tema 7. Registros
Ejemplo. Escriba un programa que desde el programa principal lea un número num y
después cargará un array con num registros de tipo Paciente con sus datos leídos desde
teclado usando la función anterior leePaciente:
void main(void){
Hospital usp;
int num,i;
Nótese el uso de la función leePaciente para leer cada uno de los registros de tipo
Paciente desde teclado y como el resultado de esa lectura se va almacenando en las
posiciones del array usp. La variable usp es un array a todos los efectos por tanto
deberá ir siempre acompañada del número real de elementos, num en este es caso.
Si hubiésemos usado la función leePaciente2, la sentencia dentro del for anterior sería:
leePaciente(&usp[i]);
Por otra parte, los arrays de registros se usan en las funciones igual que los arrays de
tipos básicos, esto es, también son argumentos de entrada/salida y deben ir
acompañados de un argumento de tipo int con el número de elementos. Así por ejemplo,
el código de una función que calculara la edad media de un array de Paciente sería:
for(i=0;i<n;i++){
suma += t[i].edad;
}
return suma/n;
}
edM = edadMedia(usp,num);
Todos los esquemas (sumar, contar, filtrar, buscar, etc) vistos en el tema 5 deben ser
usados para los arrays de struct. Lo único que cambia es que la condición normalmente
irá sobre algún campo de los registros almacenados en el array. Por ejemplo, el código
de una función para filtrar los pacientes cuya temperatura sea mayor de una dada sería:
for(i=0;i<n;i++){
if (t[i].temperatura>f){
v[m]=t[i];
m++;
}
}
return m;
}
nf=temperaturaMayor(usp,num,tf,37.5);
4. Problemas
1. Defina las constantes y tipos de datos más adecuados para el tipo siguiente:
Tipo Paciente:
Código de identificación de tipo Cadena
Array de entero con los 720 (24×30) valores de presión sanguínea tomados hora
a hora durante un mes
Array de reales con como máximo 1.000 elementos que miden el nivel de
expresión genética del paciente sometido a cierta experimentación
Número de genes (tamaño del array anterior)
2. Implemente una función tal que recibiendo un índice entero entre 0 y 719 (que sería
el índice del array de presión sanguínea) devuelva dos números enteros, el día y la hora,
a la que se tomó esa muestra. Tenga en cuenta que la primera hora es la 0 y el primer
día el 1. Por ejemplo el índice 0 es la primera hora del primer día y devolvería hora=0 y
dia=1; el índice 23 es la última hora del primer día y devolvería hora=23 y dia=1; el
número 27 la cuarta hora del segundo día y devolvería hora=3 y dia=2; y así
sucesivamente. Por ejemplo, el valor 52 daría hora=4 y dia=3. (Use los operadores de
división entera / y módulo de división entera % para este problema). La función por
tanto recibe un entero con un índice y devuelve dos valores enteros (día y hora).
5. Usando las tres funciones anteriores implemente una función tal que dado un
Paciente devuelva el día y la hora de su máxima presión sanguínea.
6. Implemente una función tal que dado un Paciente y un valor (vpres) de presión
sanguínea devuelva si supera o no en algún momento un valor mayor o igual a vpres en
su presión sanguínea. Deberá devolver un valor lógico de verdad o falso.
7. Implemente una función tal que dado un Paciente y un valor real (expgen) de
expresión genética devuelva cuántos valores del array de expresión genética de ese
Paciente son mayores de expgen.
8. Defina las constantes y tipos de datos más adecuados para el tipo siguiente:
Tipo Alumno:
DNI de tipo Cadena
Array de entero con los códigos de todas las asignaturas en las que el alumno se ha
matriculado alguna vez.
Array de reales con las notas obtenidas en las asignaturas del array anterior.
Ocupan las mismas posiciones que el array de asignaturas. Esto es, si la asignatura
de código 345 ocupa la posición 3 en el array anterior, su nota estará en la posición
3 del array de notas.
Número de asignaturas en las que el alumno se ha matriculado: tamaño de los
arrays anteriores. Máximo 50.
9. Implemente una función que reciba un Alumno y devuelva la nota mínima obtenida y
el código de la asignatura donde se obtuvo (suponga que solo hay una).
10. Implemente una función que dado un Alumno y un valor de nota (vnota) devuelva
un array con los códigos de las asignaturas con nota mayor o igual a vnota.
11. Implemente una función que reciba un Alumno y un entero representando un código
de asignatura y devuelva la nota de esa asignatura ó -1 si no ha estado matriculado.
12. Implemente una función tal que dado un Alumno y un valor real (vnota) devuelva si
todas las notas superan o no un valor mayor o igual a vnota. Deberá devolver un valor
booleano de verdad o falso.
14. Implemente una función tal que dado un Alumno devuelva la nota media de las
asignaturas en las que se ha matriculado.