Hasta ahora hemos centrado básicamente nuestro estudio en una forma adecuada de
algoritmizar problemas, o lo que es lo mismo, de encontrar algoritmos de solución para
ciertos problemas del mundo real. Para conseguirlo nos hemos basado en:
Sin embargo, existe otro gran area de conocimiento que hemos tratado con poca
profundidad hasta ahora y es la de utilizar tipos de datos “avanzados”. En nuestro
estudio hemos introducido los tipos básicos (predefinidos) como el entero, el real, el
carácter, o el lógico, y con posterioridad hemos visto como agrupar datos del mismo
tipo (homogeneos) en “almacenes” como son las tablas1. A la vez hemos estudiado que
los datos pueden proceder del dispositivo de entrada estandar (el teclado) o bien pueden
proceder de un almacenamiento permanente en disco (un fichero2). Asimismo la
escritura de resultados puede realizarse en pantalla o bien en ficheros.
De tal forma que los programas desarrollados con estructuras de datos adecuadas,
resultan de mayor nivel y legibilidad, redundando esto en su costo de mantenimiento, de
actualización y de desarrollo.
Como estructuras de datos (EDs) se conoce a todo aquello que sirva para almacenar
de forma organizada distintas informaciones que se deban manipular en los algoritmos.
Existen distintos tipos de EDs como son las listas, colas, árboles, grafos, etc., que se
salen fuera de nuestros objetivos. Sin embargo vamos a estudiar como crear nuevos
1
Comúnmente en programación se llama vectores o arrays a las tablas unidimensionales, y matrices a las
bidimensionales. Además, los arrays de caracteres se denominan cadenas o strings.
2
Los ficheros que hemos estado utilizando han sido de texto (que contienen caracteres ASCII o de otro
código), pero también pueden utilizarse ficheros binarios, cuya manipulación es más eficiente y
compacta, pero que no pueden ser abiertos con un editor de texto.
tipos de datos a partir de los ya existentes, de forma que las nuevas variables de estos
nuevos tipos puedan contener información diversa (hetereogenea). A estos tipos de
datos los llamaremos estructuras, registros o tuplas.
Definiremos en lenguaje algorítmico los nuevos tipos de datos dentro del párrafo
Utilizando, de forma que podremos utilizarlos en el fichero en el que se incluya3. Veamos
un ejemplo concreto:
Ejemplo: definición de un tipo de datos tupla para contener información relativa a una
persona. Al nuevo tipo lo llamamos persona.
Utilizando
Tipo
Persona=tupla
Nombre: cadena
Edad: entero
Telefono: cadena
ftupla
Ftipo
A partir de esta definición podemos crear variables de ese nuevo tipo, y por supuesto
podemos dar valores a sus campos, para lo que utilizaremos el operador de selección de
campo ( . ):
p, q: persona;
p.nombre:= ”pepe”
p.edad:= 23
p.telefono:= ”956662112”
Podemos asignar variables de tipo estructura directamente (por ejemplo, para dos
hermanos gemelos):
q:=p
q.nombre:= ”manolo”
Tipo
Alumno=tupla
Datos: persona
Notas: tabla[50] de real
Curso: entero
ftupla
Ftipo
De esta forma, podemos definir variables de este nuevo tipo y darle valores:
x,y: alumno
x.curso:= 1
x.notas[0]:= 5.0
x.notas[1]:= 7.5
x.datos.nombre:= “carlos”
Manipulación de tuplas
Aparte de dar valores individuales a los campos de una variable de tipo estructura,
debemos estudiar por su importancia y amplia utilización la forma de crear tablas o
vectores de tuplas y como rellenar éstas con informaciones procedentes ya sea de
teclado o de fichero.
Con estas definiciones podemos hacer, por ejemplo, que “pepe” sea nuestro primer
amigo:
lista_amigos[1].nombre:= “alfonso”
Evidentemente sobre los vectores de tuplas se pueden utilizar los mismos mecanismos
que sobre las tablas de enteros o reales que estabamos acostumbrados a manejar. Es
decir, se pueden atacar de la misma forma (con los mismos esquemas) problemas de
recorrido y de búsqueda. Veremos algunos ejemplos después del apartado siguiente.
Lectura/escritura de Tuplas desde teclado y fichero
Directamente vamos a escribir una acción para leer una serie de informaciones desde el
teclado y almacenar sus valores en un vector de registros. Como las tablas tienen una
longitud finita, debemos controlar no pasarnos del límite de valores definidos
(supongamos máximo4 100). Además el algoritmo devolverá el número de personas
introducidas en el vector, es decir que el vector no tiene porqué rellenarse de forma
completa. Como marca o persona final utilizaremos la persona cuyo nombre sea “fin”.
4
Cuando utilicemos en nuestros programas vectores o matrices de cualquier tipo, es necesario que
tengamos en cuenta que las dimensiones por defecto de memoria reservada para cada programa no son
muy amplias con lo que el tamaño de las tablas no podrá rebasar un cierto valor dependiente de cada
compilador y de algunas opciones de éste.
Para escribir en un fichero un vector incompleto de tuplas podemos hacer un recorrido
del vector hasta el número de elementos que realmente contenga:
Tipo
punto=tupla
x,y: real
ftupla
Ftipo
Ejemplo: Buscar a qué amigo pertenece un teléfono que tenemos apuntado sin su
nombre correspondiente.
Ejercicio completo
Definiendo
// definición de constantes
N=100
Utilizando
// definición de tipos
Tipo
Persona=tupla
Nombre: cadena
Edad: entero
Telefono: cadena
ftupla
Ftipo
5
Hasta ahora sólo habiamos estudiado funciones que devuelven un valor.
// prototipos de acciones y/o funciones
Acción Principal
var
nomfich1,nomfich2: cadena
lista, lista_misma_edad:tabla[N] de persona
edad,num_personas, num_edad: entero
fvar
leer(nomfich1)
num_personas:=LeerFicheroTuplas(nomfich1,lista)
si num_personas < > -1
leer(edad)
num_edad:=BuscaEdad(lista,num_personas,edad,lista_misma_edad)
leer(nomfich2)
EscribirFicheroTuplas(nomfich2,lista_misma_edad,num_edad)
sino
escribir(‘Error en la apertura del fichero de datos’)
fsi
escribir(‘Fin del programa’)
facción
Ejercicios
1. Realizar un programa en L. Algorítmico y C que permita leer dos números reales que representan los
límites inferior y superior de un intervalo, un tercero que representa el número de puntos a considerar
(no mayor de 100), y a partir de estos datos de entrada, calcule las ordenadas de todas las abcisas
comprendidas entre el límite inferior y el superior sobre un círculo de radio r (que se deberá
introducir también como entrada por teclado) centrado en el origen.
2. Ejemplo de un programa que calcula las soluciones de una ecuación de 2º grado. (versión con
devolución de una estructura, tupla o registro)
Utilizando
Tipo
raizdoble = tupla
sol1: real
sol2: real
ftupla
ftipo
función sol_ec_2grado(ent a, b, c: real): raizdoble
acción principal
var
a2, a1, a0: real
solucion: raizdoble
fvar
leer(a2, a1, a0)
solucion:=sol_ec_2grado(a2, a1, a0)
escribir(solucion)
facción
Lenguaje C
#include <stdio.h>
#include <math.h>
typedef struct{
float sol1;
float sol2;
}raizdoble;
raizdoble sol_ec_2grado(float a, float b, float c);
/************************************************************************/
/* Programa que calcula las soluciones de una ec. de 2 grado */
/* Funciones utilizadass: sol_ec_2_grado() */
/* Realizado por: Dpto LSI - Sección Algeciras */
/* Fecha de Creación: 31/03/1998 */
/* Revisión: --/--/-- (Por: ------) */
/************************************************************************/
void main(void)
{
char cad[15];
float a2, a1, a0;
raizdoble solucion;
return r;
}
4. Realizar un programa en L. Algorítmico y C que permita leer dos números reales que representan los
límites inferior y superior de un intervalo, un tercero que representa el número de puntos a considerar
(no mayor de 100), y a partir de estos datos de entrada, calcule las ordenadas de todas las abcisas
comprendidas entre el límite inferior y el superior sobre un círculo de radio r (que se deberá
introducir también como entrada por teclado) centrado en el origen, Y ESCRIBA ÉSTAS EN UN
FICHERO DE SALIDA DE DATOS.
5. Ejemplo de un programa que lee un vector de registros (de personas) desde un fichero, se almacenan
en un vector, se ordena por las edades de las personas y luego se escribe en un fichero de salida.
Lenguaje Algorítmico:
Utilizando
Tipo
persona = tupla
nombre: cadena
edad: entero
ftupla
ftipo
acción principal
var
nomfichero_entrada: cadena;
nomfichero_salida: cadena;
numero_elementos: entero
lista: tabla[10] de persona;
fvar
leer(nomfichero_entrada);
LeerFichero(nomfichero_entrada,lista,numero_elementos);
si numero_elementos <> -1
OrdenarVector(lista);
leer(nomfichero_salida);
EscribirFichero(nomfichero_salida,lista,numero_elementos);
sino
Escribir(“Lo siento, no se puedo abrir el fichero de datos.”);
fsi
facción
Lenguaje C
#include <stdio.h>
#include <string.h>
typedef struct{
char nombre[40+1];
int edad;
}persona;
void main(void)
{
char nomfichero_entrada[20+1];
char nomfichero_salida[20+1];
int numero_elementos;
persona lista[10];
S= fopen (nomfich,"rt");
if (S==NULL) exit(1);
i=0;
while (!feof(S))
{
fscanf(S,"%s%d\n",p.nombre, &p.edad);
strcpy(v[i].nombre, p.nombre);
v[i].edad = p.edad;
i = i+1;
}
fclose(S);
*numitems = i;
}
S = fopen (nomfich,"wt");
if (S==NULL) exit(1);
for(i=0;i<numitems;i++)
fprintf(S,"%s %d\n",v[i].nombre,v[i].edad);
fclose(S);
}
• Se dispone de un fichero de tuplas (x,y,z) que determina una figura en el espacio tridimensional. El
tamaño máximo que el fichero podrá alcanzar será 100+M tuplas.
• Se dispone de otro fichero que contiene una matriz 3x3 de transformación de puntos en el espacio.
• Se desea obtener un fichero que contenga los puntos del fichero original transformados (según la
matriz antes mencionada), y ordenados según su distancia al origen de coordenadas.
Nota: El alumno deberá crear los dos ficheros de entrada para las pruebas del programa.
Solución
PRINCIPAL
ESCRIBIR
LEER VECTOR LEER MATRIZ DE OBTENER VECTOR ORDENAR
FICHERO DE
DE PUNTOS TRANSFORMACIÓN TRANSFORMADO VECTOR
SALIDA
LEER VECTOR DE PUNTOS: A partir de un nombre de fichero, carga las tuplas contenidas en un vector
de tuplas, dando a la salida en número de tuplas cargadas.
LEER MATRIZ DE TRANSFORMACIÓN: A partir de un nombre de fichero, carga los nueve números
que contiene en una matriz de 3x3.
ORDENAR VECTOR: A partir de un vector de tuplas y el número de tuplas a procesar, ordena este
vector con el criterio de la mínima distancia al origen.
Utilizando
tipo
tupla = punto
x,y,z: real;
ftupla
ftipo
función LeerVectorPuntos(ent nom: cadena, sal v: tabla[100] de punto):entero;
función LeerMatriz(ent nom:cadena, sal m: tabla[3][3] de real):lógico;
acción ObtenerTransformado(ent v: tabla [100] de punto, num_tuplas:entero,
m: tabla[3][3] de real,
sal vt: tabla [100] de punto);
acción OrdenarVector(ent numitems:entero, sal v: tabla[100] de punto);
acción EscribirVector(ent nom: cadena, v: tabla [100] de punto,num_tuplas:entero);
acción principal
var
nombre_fichero: cadena;
num_tuplas: entero;
v, vt: tabla [100] de punto;
m: tabla [3][3] de real;
error: lógico;
fvar
leer(nombre_fichero);
num_tuplas:=LeerVectorPuntos(nombre_fichero,v);
si num_tuplas <> -1
leer(nombre_fichero);
error:=LeerMatriz (nombre_fichero,m);
si error=FALSO
ObtenerTransformado(v, num_tuplas, m, vt);
OrdenarVector(num_tuplas, v);
leer(nombre_fichero);
EscribirVector(nombre_fichero,vt, num_tuplas);
// se podría controlar también un posible error al escribir en el fichero
sino
escribir(“Lo siento, no se pudo abrir el fichero de la matriz”);
fsi
sino
escribir(“Lo siento, no se pudo abrir el fichero de datos”);
fsi
facción
• Se dispone de un fichero, en el que en cada fila se encuentra almacenado un segmento de línea dado
por dos puntos del espacio tridimensional (inicial y final). El tamaño máximo que el fichero podrá
alcanzar será de 100+M segmentos de línea.
• Se desea obtener un fichero que contenga la polilínea formada por los segmentos de línea que unen
los puntos medios de los segmentos originales
Lenguaje Algoritmico:
Definiendo
N=100
Utilizando
Tipo
punto=tupla
x,y,z: real;
ftupla
Ftipo
Tipo
segmento=tupla
Inicio:punto;
Fin:punto;
ftupla
ftipo
funcion LeerFicheroSegmentos (ent nomfich: cadena,
ent/sal poli: tabla[N] de segmento):entero;
accion EncontrarPolilineaMedia (ent pol1: tabla[N] de segmento,
ent/sal pol2: tabla[N] de segmento,
ent num_segmentos: entero);
accion CalcularPuntosMedios (ent pol: tabla[N] de segmento,
ent/sal pm : tabla[N] de punto,
ent num_segmentos: entero);
funcion PuntoMedioSegmento (ent p: punto, ent q: punto):punto;
accion EscribirSegmentosFichero (ent nomfich: cadena, ent pol: tabla[N] de segmento,
ent num_segmentos: entero);
Acción principal
var
num_segmentos: entero;
polilinea1, polilinea2 : tabla [N] de segmento;
pm: tabla[N] de punto;
nomfich_entrada, nomfich_salida: cadena;
fvar
Leer(nomfich_entrada);
num_segmentos:=LeerFicheroSegmentos(nomfich_entrada,polilinea1);
si num_segmentos<>-1
EncontrarPolilineaMedia(polilinea1,polilinea2,num_segmentos);
Leer(nomfich_salida);
EscribirSegmentosFichero(nomfich_salida,polilinea2,num_segmentos);
sino
escribir(“Lo siento, hubo error en la apertura”);
faccion
• Se desea realizar un sistema de clasificación automática de objetos situados en puntos del plano, de
tal forma que como entrada se dispone de un fichero, en el que en cada fila se encuentran
almacenadas las coordenadas planas de un punto y una propiedad de cada punto que puede valer 1 ó
2, y que indica su pertenencia a la clase de puntos C1 o a la clase C2 (ver figura). El tamaño máximo
que el fichero podrá alcanzar será de 100+M puntos.
2
1
0
0 1 2 ...
Fichero de Entrada:
0,0,1
0,1,1
0,2,1
0,3,2
1,0,1
1,1,1
1,2,1
1,3,1
2,0,2
2,1,1
...
• En un fichero (1) tenemos la descripción de una estructura metálica plana formada por barras, como
en:
• En otro fichero (2), tenemos cuanto pesa por metro cada uno de los distintos tipos de perfiles:
TipoPerfil Peso
IPN-100 175
IPN-200 250
UPN-100 150
...
• En un último fichero (3), tenemos las coordenadas de cada nodo de la estructura en el plano:
Nodo X Y
0 10 0
1 5 0
2 5 5
3 0 0
• Los ficheros (1) y (3), son definidos por el usuario de un paquete de cálculo de estructuras, el fichero
(2) es propio del paquete (aunque para este ejercicio debe escribirse)
• Se pide :
A) Que el programa actualice el fichero (1) para que además contenga otro campo, que almacene la
longitud de cada barra de la estructura
B) Calcular el peso total de la estructura definida
Dados dos ficheros, el primero en el que en cada línea tenemos el dni, el nombre y la edad de una persona
y el segundo en el que tenemos en cada línea el dni e información acerca de la matriculación en las
asignaturas A,B,C,D y E, como se muestra (máximo 100 en cada fichero):
Fichero (1):
DNI NOMBRE EDAD
14236578 pepe 20
12345678 pepi 19
21435678 pepon 21
...
Fichero (2):
DNI A BCDE
14236578 1 0 0 01
12345678 0 1 1 10
21435678 1 1 1 11
...
Se pide:
• Edad media de los matriculados en cada asignatura (por pantalla).
• Listados de DNI y NOMBRE de los que estén matriculados en A, B y C.
Lenguaje Algoritmico:
Definiendo
N=100
Utilizando
Tipo
persona=tupla
dni: cadena
nombre: cadena
edad: entero
ftupla
Ftipo
Tipo
matricula=tupla
dni: cadena
a,b,c,d,e: booleano;
ftupla
ftipo
Acción principal
var
num_personas1, num_personas2, matriculados: entero;
lista, lista_matriculados : tabla [N] de persona;
datos: tabla[N] de matricula;
v: tabla[N] de entero;
nomfich_entrada1, nomfich_entrada2, nomfich_salida: cadena;
fvar
// se deja como ejercicio controlar los posibles errores en las aperturas de los ficheros
Leer(nomfich_entrada1);
numpersonas1:=LeerFicheroPersonas(nomfich_entrada1,lista);
Leer(nomfich_entrada2);
numpersonas2:=LeerFicheroDatos(nomfich_entrada2,datos);
Bibliografía6
[AHU88] Aho A. V., Hopcroft J. E., Ullman J. D., Estructuras de datos y algoritmos.
Addison-Wesley Iberoamericana ,1988.
[AM97] Antonakos J. L., Mansfield K. C., Programación estructurada en C,
PrenticeHall, 1997.
[BB97] Brassard G., Bratley P., Fundamentos de Algoritmia, Prentice Hall, 1997.
[BC85] Biondi J., Clavel G., Introducción a la programación. Tomo 1: algoritmos y
lenguajes, Masson, 1985.
[CC97] Cerrada J., Collado M., Programación I, Universidad Nacional de Educación a
Distancia, 1997.
[CCM93] Castro, J.; Cucker, F.; Messeguer, X.; Rubio, A.; Solano, Ll.; Valles, B. Curso
de Programación. Editorial Mc.Graw-Hill, 1993.
[CF97] Cerrada C., Feliu V., Estructura y tecnología de computadores I, Universidad
Nacional de Educación a Distancia, 1997.
[ChC87] Chapra, Steven C.; Canale, Raimond P. Métodos Numéricos para Ingenieros.
Editorial Mc.Graw-Hill
[Fai87] Fairley, Richard. Ingeniería de Software. Editorial McGraw-Hill, 1987.
[GGS93] Galve, J; González, J; Sánchez, A; Velázquez, J. Algoritmica. Diseño y
análisis de algoritmos funcionales e imperativos. Editorial Ra-Ma, 1993.
[Joy87] Joyanes, L. Metodología de la Programación. Editorial Mc.Graw-Hill, 1987.
[Joy92] Joyanes Aguilar, Luis. Fundamentos de Programación. Algoritmos y
Estructuras de Datos. 2ª Edición. Editorial McGraw-Hill, 1992.
[Knu86] Knuth, D.E. Algoritmos Fundamentales. Volumen I. Editorial Reverte, 1986.
[KR88] Kernighan, B; Ritchie, D. El Lenguaje de Programación C. 5ª R. Editorial
Prentice-Hall, 1988.
[Lip87] Lipschutz, S. Estructuras de Datos. Editorial Mc.Graw-Hill, 1987.
6
Como en los anteriores capítulos, todas las referencias bibliografías se encuentran disponibles en la
biblioteca de la Escuela Politécnica Superior de Algeciras
[LS85] Lewis, T; Smith, M. Estructuras de Datos. Programación y Aplicaciones.
Editorial Paraninfo, 1985.
[PTV92] Press, W; Teukolsky, S; Vetterling, W; Flannery, B. Numerical Recipes in C.
The Art of Scientific Computing. 2ª Edición. Cambridge University Press,
1992.
[Sch88] Schildt, H. C - Manual de Referencia. Editorial Mc.Graw-Hill, 1988.
[Sch91] Schildt, H. Ansi C a su alcance. Editorial Mc.Graw-Hill, 1991.
[Sch95] Schildt, H. Turbo C/C++ v.3.1- Manual de Referencia. Editorial Mc.Graw-
Hill, 1995.
[SGTLL97] Sanchez, P.J; Galindo, J.; Turias, I.; Lloret, I. Ejercicios Resueltos de
Programación en C. Servicio de Publicaciones de la Universidad de Cádiz,
1997.
[SK86] Sobelman, G.; Krekelberg, D. Técnicas avanzadas en C. Desarrollo de
aplicaciones. Editorial Anaya-Multimedia, 1986.
[SP91] Scoll P. C., Peyrin J.P., Esquemas algorítmicos fundamentales: secuencias e
iteración, Masson, 1991.
[TLL96] Turias, Ignacio; Lloret, Isidro. Guía Práctica de Programación en C. Dpto.
Lenguajes y Sistemas Informáticos. UCA, 1996.
[WPM89] Waite, M; Prata, S.; Martin, D. Programación en C. Introducción y conceptos
avanzados. 2ª Edición. Editorial Anaya-Multimedia, 1989.