Академический Документы
Профессиональный Документы
Культура Документы
HolaMundo.pascal(online):Captulo6
Ms Siguienteblog
Crearblog Acceder
.c
.java
7 DE AG O STO DE 2 0 0 7
Captulo 6
.
type
Entero=integer;
Cadena=string[20];
Recursos / Download
var
//definounavariabledetipoEntero
e:Entero;
//definounavariabledetipoCadena
s:Cadena;
begin
e:=10;
s:='Prueba';
writeln(e,'',s);
end.
Contenidos
1 Introduccin
2 Operadores
3 Procedimientos y Funciones
4 Corte de Control
En este captulo nos interesa definir tipos de datos compuestos, es decir: tipos de datos que
agrupen dos o ms datos simples.
5 Arrays
6 Archivos de Registros
Registros
Llamamos registro o estructura a un tipo de datos definido por el programador que agrupa dos
o ms datos relacionados entre s, a los que llamaremos campos.
Veamos un programa que define un registro RAlumno que contiene 3 campos: legajo, nombre
y fecNac.
7 Estructuras Dinmicas
8 Arboles y Recursividad
9 Teora de Objetos (intro)
EjemplosResueltos
testRecord.pas
1:
2:
3:
4:
5:
6:
Ahora en Video!
type
//definimosunnuevotipodedatos
//un"registro"
RAlumno=record
http://holamundopascal.blogspot.mx/2007/08/capitulo6.html
1/24
15/10/2015
HolaMundo.pascal(online):Captulo6
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
legajo:integer;
nombre:string[20];
fecNac:longint;//aaaammdd
end;
varalumno:RAlumno;
begin
//leemosellegajo
write('IngreseLegajo:');
readln(alumno.legajo);
//leemoselnombre
write('IngreseNombre:');
readln(alumno.nombre);
//leemoslafecha
write('IngreseFecha(aaaammdd):');
readln(alumno.fecNac);
//imprimimoslosdatos
writeln('Legajo:',alumno.legajo);
writeln('Nombre:',alumno.nombre);
writeln('Fecha:',alumno.fecNac);
end.
No al blog de Java
Por convensin utilizaremos el prefijo R para indicar que el tipo de datos corresponde a un
registro. Por ejemplo: REmpleado, RAlumno, etc.
Super Baterista
type
//definimosunregistroRFecha
RFecha=record
dia:integer;
mes:integer;
anio:integer;//nousamosla"enie"
end;
RAlumno=record
legajo:integer;
nombre:string[20];
fecNac:RFecha;//estecampoestipoRFecha
end;
varalumno:RAlumno;
begin
alumno.fecNac.dia:=2;
alumno.fecNac.mes:=10;
alumno.fecNac.anio:=1970;
end.
Archivos
http://holamundopascal.blogspot.mx/2007/08/capitulo6.html
2/24
15/10/2015
HolaMundo.pascal(online):Captulo6
Grabar un Archivo
Veamos el cdigo de un programa que lee valores numricos por teclado y los graba en un
archivo llamado SALIDA.dat.
grabarArchivo.pas
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
type
FInteger=fileofinteger;
var
arch:FInteger;//variabledearchivo
v:integer;
begin
//relacionamoslavariabledearchivocon
//elarchivofisicoendisco:SALIDA.dat
assign(arch,'SALIDA.dat');
//sielarchivonoexisteentonceslocrea
//sielarchivoexisteentonceslovacia
rewrite(arch);
//leemosunvalorporteclado(tipointeger)
read(v);
//finalizamoslacargadedatosconcero
while(v<>0)dobegin
//escribimosenelarchivoelvalorleido
write(arch,v);
//leemoselsiguientevalor(porteclado)
read(v);
end;
//cierraelarchivo
close(arch);
end.
Anlisis
Analizando el cdigo anterior podremos ver los puntos fundamentales para poder manejar
archivos dentro de un programa.
Comenzamos definiendo un tipo de datos propio para el archivo. El tipo FInteger. Por
convensin utilizaremos el prefijo F para identificar los tipos de datos que se refieren a
archivos.
Recordemos que el archivo contendr valores numricos ingresados por teclado. As que un
archivo de integer estar bien (siempre que no se ingresen valores con decimales o valores
mayores que 32767). Tambin definimos una variable del tipo FInteger. La variable arch.
1:
2:
3:
4:
5:
6:
7:
8:
type
FInteger=fileofinteger;
var
arch:FInteger;//variabledearchivo
v:integer;
http://holamundopascal.blogspot.mx/2007/08/capitulo6.html
3/24
15/10/2015
HolaMundo.pascal(online):Captulo6
Teniendo definido el tipo del archivo y una variable de ese tipo para manejarlo tenemos que
relacionar la variable de archivo (arch) con un archivo fsico en el disco. En el ejemplo el
archivo fsico ser SALIDA.dat. Con la funcin assign establecemos esta relacin y luego con
la funcin rewrite creamos el archivo. Es decir: si no exista lo crea y si exista lo deja vacio
(con 0 bytes).
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
begin
//relacionamoslavariabledearchivocon
//elarchivofisicoendisco:SALIDA.dat
assign(arch,'SALIDA.dat');
//sielarchivonoexisteentonceslocrea
//sielarchivoexisteentonceslovacia
rewrite(arch);
El prximo paso es leer valores por teclado (finalizando con cero) y grabarlos en el archivo.
Para esto utilizamos la funcin write. Esta funcin recibe como parmetro la variable de
archivo (arch) y el valor que queremos grabar (v). Obviamente el valor tiene que ser del
mismo tipo del archivo. Como este archivo es de integer entonces lo que vayamos a grabar en
l tiene que ser de tipo integer tambin.
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
//leemosunvalorporteclado(tipointeger)
read(v);
//finalizamoslacargadedatosconcero
while(v<>0)dobegin
//escribimosenelarchivoelvalorleido
write(arch,v);
//leemoselsiguientevalor(porteclado)
read(v);
end;
Por ltimo es necesario cerrar el archivo. El archivo se abre y se cierra. Para cerrarlo
utilizamos la funcin close.
1:
2: //cierraelarchivo
3: close(arch);
4: end.
5:
Leer un Archivo
Veamos ahora el cdigo de un programa que lee el archivo SALIDA.dat (generado en el
problema anterior) y muestra por pantalla su contenido.
leerArchivo.pas
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
type
FInteger=fileofinteger;
var
arch:FInteger;
v:integer;
begin
//relacionalavariabledearchivo
//conelarchivofisicoSALIDA.dat
assign(arch,'SALIDA.dat');
//abreelarchivo
reset(arch);
http://holamundopascal.blogspot.mx/2007/08/capitulo6.html
4/24
15/10/2015
HolaMundo.pascal(online):Captulo6
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
//mientrasnollegueelfindearchivo(eof)
while(NOTeof(arch))dobegin
//leeelarchivoyasignaelvalorleido
//alavariablev(queesdelmismotipo
//delarchivo:integer)
read(arch,v);
//muestroelvalorleido
writeln(v);
end;
//cierraelarchivo
close(arch);
end.
Anlisis
Analizando el cdigo anterior vemos lo siguiente. Para abrir el archivo (luego del assign)
utilizamos la funcion reset. Esta funcin abre para lectura/escritura el archivo pero no borra
su contenido.
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
type
FInteger=fileofinteger;
var
arch:FInteger;
v:integer;
begin
//relacionalavariabledearchivo
//conelarchivofisicoSALIDA.dat
assign(arch,'SALIDA.dat');
//abreelarchivo
reset(arch);
A continuacin iteramos mientras no llegue el fin del archivo. Para esto utilizamos la funcin
eof ("end of file") que retorna true al momento de leer el ltimo registro. Dentro de while
leemos con la funcin read. Esta funcin recibe la variable de archivo (arch) y una variable
del mismo tipo del archivo en la cual va a asignar el valor leido (v).
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
//mientrasnollegueelfindearchivo(eof)
while(NOTeof(arch))dobegin
//leeelarchivoyasignaelvalorleido
//alavariablev(queesdelmismotipo
//delarchivo:integer)
read(arch,v);
//muestroelvalorleido
writeln(v);
end;
//cierraelarchivo
close(arch);
end.
Veamos los diagramas para los programas grabarArchivo (izquierda) y leerArchivo (derecha).
http://holamundopascal.blogspot.mx/2007/08/capitulo6.html
5/24
15/10/2015
HolaMundo.pascal(online):Captulo6
Siguiendo el grfico paso a paso vemos que al hacer reset el puntero apunta al primer
registro. Luego, el primer read retorna 'Analia' y el puntero queda en el segundo registro. El
prximo read retorna 'Pablo' y el puntero queda en el tercer registro. El prximo read retorna
'Silvia' y el puntero pasa al fin de archivo (es decir: la funcin eof da true en ese mismo
momento).
Tenemos que tener mucho cuidado al momento de "barrer" un archivo (leerlo integramente
desde el primer registro hasta el ltimo) porque la funcin eof da true al momento de leer el
ltimo registro, no luego de leerlo.
http://holamundopascal.blogspot.mx/2007/08/capitulo6.html
6/24
15/10/2015
HolaMundo.pascal(online):Captulo6
//:
read(arch,nom);//leoantesdeentrar
while(NOTeof(arch))dobegin
writeln(nom);
read(arch,nom);//leoantesdecerrar
end;
//:
Leer afuera del while y volver a leer antes de cerrarlo hace que el ltimo registro no se
procese. Esto es porque al leer el ltimo registro la funcin eof retorna true y entonces el
while no vuelve a iterar.
Correcto:
11:
12:
13:
14:
15:
16:
17:
18:
19:
//:
while(NOTeof(arch))dobegin
read(arch,nom);//leonibienentra
writeln(nom);
end;
//:
Leer una nica vez adentro, al inicio del while, soluciona el problema y permite procesar
todos los registros.
http://holamundopascal.blogspot.mx/2007/08/capitulo6.html
7/24
15/10/2015
HolaMundo.pascal(online):Captulo6
El problema del eof puede resultar un poco molesto. En realidad, lo intuitivo (al menos para
mi) es que eof de true luego de leerse el ltimo registro, no al mismo momento de leerlo.
Para solucionar esto y poder leer antes de entrar y antes de finalizar el while podemos
programar una funcin (muy simple) que retorne true si lleg el eof y false si no lleg (y en
este caso que lea el registro).
type
FInteger=fileofinteger;
//funcionleerArchivo:
//sieseofretornatrue,sinoentonces
//leeelarchivoyretornafalse
functionleerArchivo(vara:FInteger
;varbuff:integer):boolean;
begin
if(eof(a))thenbegin
leerArchivo:=true;
endelsebegin
read(a,buff);
leerArchivo:=false;
end;
end;
//programaprincipal
var
arch:FInteger;
v:integer;
fin:boolean;
begin
assign(arch,'SALIDA.dat');
reset(arch);
//leemosafueradelwhileutilizando
//lafuncionleerArchivo
fin:=leerArchivo(arch,v);
while(NOTfin)dobegin
writeln(v);
//volvemosaleerantesdecerrar
//elwhileutilizandolafuncion
fin:=leerArchivo(arch,v);
end;
close(arch);
end.
http://holamundopascal.blogspot.mx/2007/08/capitulo6.html
8/24
15/10/2015
HolaMundo.pascal(online):Captulo6
El siguiente programa utiliza la funcionalidad de acceso directo para leer arbitrariamente los
registros del archivo PERSONAS.dat. El usuario ingresa el nmero de registro que quiere ver y
el programa lo muestra. As hasta que se ingrese un nmero de registro negativo.
testAccesoDirecto.pas
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
type
RPersona=record
nombre:string[20];
edad:integer;
end;
FPersona=fileofRPersona;
//programaprincipal
var
arch:FPersona;
reg:RPersona;
cantReg,pos:integer;
begin
//abroelarchivoparaleerlo
assign(arch,'PERSONAS.dat');
reset(arch);
//obtengolacantidadderegistrosque
//tieneelarchivo
cantReg:=filesize(arch);
writeln('Elarchivotiene:'
,cantReg,'registros.');
//elusuarioingresaelnro.deregistro
//quequiereleer
write('IngreseNro.Registro(0,'
,cantReg1,'):');
readln(pos);
while(pos>=0)dobegin
//posicionoelpuntero
seek(arch,pos);
//leoelregistroapuntadoporelpuntero
read(arch,reg);
//muestrolainformacion
writeln(reg.nombre,',',reg.edad);
//vuelvoapediralusuarioque
//ingreseelproximonro.deregistro
write('IngreseNro.Registro(0,'
,cantReg1,'):');
readln(pos);
end;
close(arch);
end.
Notemos que la posicin de los registros se cuenta a partir de 0 (cero). Por este motivo la
http://holamundopascal.blogspot.mx/2007/08/capitulo6.html
9/24
15/10/2015
HolaMundo.pascal(online):Captulo6
funcin seek puede posicionarse entre los registros 0 y n1 (siendo n la cantidad de registros
del archivo).
Es decir: si filesize(arch) = n entonces seek(arch,0) posiciona el puntero en el primer
registro, seek(arch, 1) posiciona el puntero en el segundo registro y... seek(arch,n1)
posiciona el puntero en el ltimo registro.
Veamos el diagrama:
Ordenamiento de Archivos
Lamentablemente no hay forma de ordenar los registros de un archivo sin que esto implique
reescribir nuevamente el archivo. Es decir: ordenar un archivo implica escribirlo de nuevo.
Por esto (sobre todo para archivos grandes) el proceso de ordenamiento suele ser costoso (en
trminos de procesamiento). Debemos ser prudentes al momento de considerarlo como una
opcin vlida.
http://holamundopascal.blogspot.mx/2007/08/capitulo6.html
10/24
15/10/2015
HolaMundo.pascal(online):Captulo6
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
type
RPersona=record
nombre:string[20];
edad:integer;
end;
FPersona=fileofRPersona;
//unarrayde100registrosRPersona
ARPersona=array[1..100]ofRPersona;
Con la seccin type definida, veamos el diagrama del algoritmo que resuelve el problema y
luego continuaremos con el resto del cdigo.
Para resolver el problema abrimos el archivo, lo subimos al array con la funcin subirArchivo,
ordenamos el array con el procedimiento ordenar, vaciamos el archivo con rewrite y bajamos
al archivo el contenido del array (con el procedimiento bajarArchivo).
Notemos que la funcin subirArchivo retorna un entero (len) que indica la cantidad de
elementos tiles que se insertaron en el array.
Que el array sea de 100 elementos no significa que los 100 elementos estn siendo utilizados.
Lo definimos de 100 porque ese es el nmero mximo de registros que puede tener el archivo
(segn el enunciado). Pero si el archivo tiene 20 registros entonces len (el valor de retorno de
la funcin) ser 20.
functionsubirArchivo(vara:FPersona
;vararr:ARPersona):integer;
varreg:RPersona;i:integer;
begin
i:=0;
while(NOTeof(a))dobegin
http://holamundopascal.blogspot.mx/2007/08/capitulo6.html
11/24
15/10/2015
HolaMundo.pascal(online):Captulo6
20:
21:
22:
23:
24:
25:
26:
27:
read(a,reg);
i:=i+1;
arr[i]:=reg;
end;
subirArchivo:=i;
end;
La funcin recorre el archivo (lo recibe abierto), asigna al array en la posicin i el registro
leido (reg) e incrementa el valor de i. Es decir que al finalizar el while, en i tendremos la
cantidad de registros que se insertaron en el array. Por eso el valor de retorno ser i.
procedure ordenar
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
procedureordenar(vararr:ARPersona;len:integer);
varordenado:boolean;i:integer;aux:RPersona;
begin
ordenado:=false;
while(NOTordenado)dobegin
ordenado:=true;
fori:=1tolen1dobegin
if(arr[i+1].nombre<arr[i].nombre)thenbegin
aux:=arr[i];
arr[i]:=arr[i+1];
arr[i+1]:=aux;
ordenado:=false;
end;
end;
end;
end;
procedurebajarArchivo(vara:FPersona
;vararr:ARPersona
;len:integer);
varreg:RPersona;i:integer;
begin
fori:=1tolendobegin
write(a,arr[i]);
end;
end;
Recorre el array y graba en el archivo (abierto y vacio) cada uno de los registros del array.
Recordemos que tanto el array como el archivo contienen registros del mismo tipo: RPersona.
programa principal
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
//programaprincipal
vararch:FPersona;arr:ARPersona;len:integer;
begin
//abroelarchivo
assign(arch,'PERSONAS.dat');
reset(arch);
//losuboaunarrayderegistros
len:=subirArchivo(arch,arr);
//ordenoelarray
ordenar(arr,len);
//reescriboelarchivo
http://holamundopascal.blogspot.mx/2007/08/capitulo6.html
12/24
15/10/2015
HolaMundo.pascal(online):Captulo6
75:
76:
77:
78:
79:
80:
81:
82:
rewrite(arch);
//graboenelarchivolosregistrosdelarray
bajarArchivo(arch,arr,len);
close(arch);
end.
Supongamos que tenemos el archivo EMPLEADOS.dat ordenado por el campo legajo con el
siguiente formato de registro:
REmpleado = record
..legajo: integer;
..nombre: string[20];
end;
Entonces podemos analizar la funcin buscarBinArch que realiza una bsqueda binaria sobre
este archivo y retorna (en un valor entero) la posicin del registro que contiene el valor
(legajo) que estamos buscando (si existe) o un valor negativo si no existe lo que buscamos.
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
functionbuscarBinArch(vararch:FEmpleado
;v:integer
;varreg:REmpleado):integer;
vari,j,k:integer;encontrado:boolean;
begin
encontrado:=false;
//icomeinzaencero(primerposicion)
i:=0;
//japuntaalultimoregistro(recordemosque
//senumerandesdecero)
j:=filesize(arch)1;
while((i<=j)AND(NOTencontrado))dobegin
//calculolaposicionpromedio
k:=(i+j)div2;
//posicionoelpunteroyleo
seek(arch,k);
read(arch,reg);
if(reg.legajo=v)thenbegin
encontrado:=true;
endelsebegin
if(reg.legajo<v)thenbegin
i:=k+1;
endelsebegin
j:=k1;
end;
end;
end;
if(i>j)thenbegin
buscarBinArch:=1;
endelsebegin
buscarBinArch:=k;
end;
end;
Comparando con la bsqueda binaria sobre arrays las nicas diferencias son:
http://holamundopascal.blogspot.mx/2007/08/capitulo6.html
13/24
15/10/2015
HolaMundo.pascal(online):Captulo6
1 j se inicializa con la posicin del ltimo registro del archivo (menos 1 porque los registros
se numeran desde cero) y
2 Luego de calcular el valor de k hacemos un acceso directo al archivo para leer el registro
ubicado en esa posicin.
Notemos que el parmetro reg lo recibimos por referencia por lo tanto cuando leemos en el
archivo y utilizamos esta variable para que la funcin read guarde all lo que ley, los datos
leidos quedarn en la variable an despues de finalizar la funcin buscarBinArch.
Ahora veamos un programa principal que le pide al usuario que ingrese legajos y (si existen)
muestra los datos completos del registro encontrado.
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
//programaprincipal
varpos,leg:integer;arch:FEmpleado;reg:REmpleado;
begin
assign(arch,'EMPLEADOS.dat');
reset(arch);
write('Legajo:');
readln(leg);
while(leg>0)dobegin
//busquedabinariasobreelarchivo
pos:=buscarBinArch(arch,leg,reg);
if(pos>=0)thenbegin
writeln('Encontrado(',pos,'):'
,reg.legajo,','
,reg.nombre);
endelsebegin
writeln('Legajonoencontrado');
end;
write('Legajo:');
readln(leg);
end;
close(arch);
end.
Notemos que la funcin buscarBinArch retorna un entero positivo indicando en que posicin
fu encontrado el registro cuyo campo legajo es el que estamos buscando. Si la funcin
retorna un valor negativo significa que no se encontr ningn registro con ese legajo.
Si el registro se encontr entonces la misma funcin ya deja cargados los datos del registro en
la variable reg.
http://holamundopascal.blogspot.mx/2007/08/capitulo6.html
14/24
15/10/2015
HolaMundo.pascal(online):Captulo6
Indexar Archivos
Como dijimos anteriormente, no siempre es una buena idea ordenar el archivo. Y si el archivo
no est ordenado entonces no se puede realizar una bsqueda binaria sobre l. Tenemos un
problema.
La solucin consiste en crear un ndice ordenado por el campo por el cual queremos realizar la
bsqueda y luego acceder a los registros del archivo de manera directa, previa bsqueda sobre
el ndice.
El ndice se puede implementar en un array (si la cantidad de registros del archivo est
acotada) o en una lista enlazada.
http://holamundopascal.blogspot.mx/2007/08/capitulo6.html
15/24
15/10/2015
HolaMundo.pascal(online):Captulo6
En el ejemplo vemos que el array qued ordenado por legajo. As podremos realizar una
bsqueda binaria sobre el array para buscar (por ejemplo) el legajo nmero 271. Cuando lo
encontremos veremos que el campo posArch dir 1. Entonces si accedemos al archivo, al
registro nmero 1 habremos encontrado el registro que estbamos buscando.
Analicemos entonces la funcin indexaEmpleados que lee el archivo y genera el array ndice
sobre el que luego se podr realizar la bsqueda binaria por la clave legajo.
Primero veamos la seccin type donde definimos los tipos REmpleado (registros del archivo),
FEmpleado (tipo del archivo), RIndice (registros del array) ARIndice (tipo que define un
array de 100 RIndice).
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
type
REmpleado=record
legajo:integer;
nombre:string[20];
end;
FEmpleado=fileofREmpleado;
RIndice=record
legajo:integer;
posArch:integer;//posicionenelarchivo
end;
ARIndice=array[1..100]ofRIndice;
Veamos ahora la funcin indexarEmpleados. Esta funcin recibe el archivo arch (ya abierto)
y el array arr (vacio, sin elementos). Retorna la cantidad de elementos tiles que se
insertaron en el array (len).
El objetivo de la funcin es recorrer el archivo arch y por cada registro del archivo ir
insertando (ordenado por legajo) registros (de tipo ARIndice) en el array arr.
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
functionindexarEmpleados(vararch:FEmpleado
;vararr:ARIndice):integer;
varlen:integer;reg:REmpleado;regArr:RIndice;
begin
len:=0;
while(NOTeof(arch))dobegin
read(arch,reg);
regArr.legajo:=reg.legajo;
regArr.posArch:=len;
insertarOrdenado(arr,len,regArr);
end;
indexarEmpleados:=len;
end;
Como vemos, el algoritmo que resuelve la funcin es muy simple: recorre el archivo, por cada
http://holamundopascal.blogspot.mx/2007/08/capitulo6.html
16/24
15/10/2015
HolaMundo.pascal(online):Captulo6
registro del archivo asigna el legajo y la posicin en el archivo del registro leido (que coincide
con len) en un registro de tipo RIndice. Luego, utilizando la funcin insertarOrdenado
inserta ese registro en el array.
Cabe aclarar que en este caso la funcin insertarOrdenado fue modificada. El array que
recibe es de tipo ARIndice y el valor que recibe para insertar es de tipo RIndice. Y en todas
las condiciones lgicas pregunta por arr[i].legajo o valor.legajo ya que legajo es el campo
clave.
Veamos el cdigo del procedimiento insertar y de la funcin insertarOrdenado adaptados
para este problema.
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
procedureinsertar(vararr:ARIndice
;varlen:integer
;valor:RIndice;pos:integer);
vari:integer;
begin
fori:=len+1downtopos+1dobegin
arr[i]:=arr[i1];
end;
arr[pos]:=valor;
len:=len+1;
end;
functioninsertarOrdenado(vararr:ARIndice
;varlen:integer
;valor:RIndice):integer;
vari:integer;
begin
i:=1;
while((i<=len)AND(arr[i].legajo<=valor.legajo))
dobegin
i:=i+1;
end;
if(i>len)thenbegin
len:=len+1;
arr[len]:=valor;
insertarOrdenado:=len;
endelsebegin
insertar(arr,len,valor,i);
http://holamundopascal.blogspot.mx/2007/08/capitulo6.html
17/24
15/10/2015
HolaMundo.pascal(online):Captulo6
48: insertarOrdenado:=i;
49: end;
50: end;
51:
Ahora podemos ver el programa principal. Pide al usuario que ingrese un legajo, lo busca en el
ndice y (si existe) accede directamente al archivo para leer y mostrar los datos del empleado.
//programaprincipal
var
arch:FEmpleado;
arrIndice:ARIndice;
reg:REmpleado;
len,leg,posArr,posArch:integer;
begin
assign(arch,'EMPLEADOS.dat');
reset(arch);
len:=indexarEmpleados(arch,arrIndice);
write('IngreseLegajo:');
readln(leg);
while(leg>0)dobegin
posArr:=buscarBinIndex(arrIndice,len,leg);
if(posArr>0)thenbegin
posArch:=arrIndice[posArr].posArch;
seek(arch,posArch);
read(arch,reg);
writeln('Legajo:',reg.legajo
,'Nombre:',reg.nombre);
endelsebegin
writeln('Legajonoencontrado');
end;
write('IngreseLegajo:');
http://holamundopascal.blogspot.mx/2007/08/capitulo6.html
18/24
15/10/2015
HolaMundo.pascal(online):Captulo6
129:
130:
131:
132:
133:
readln(leg);
end;
close(arch);
end.
Apareo de Archivos
Se considera "apareo de archivos" a los problemas que intercalan datos de dos o ms archivos
que se encuentran ordenados por la misma clave, recorrindolos simultaneamente.
Analicemos los datos de los siguientes conjuntos:
Los dos conjuntos estn ordenados en forma ascendente. Leemos el primer valor de A (lo
llamaremos a) y luego el primer valor de B (lo llamaremos b).
Si a(1) < b(2) podemos determinar que el valor a est en el conjunto A pero no en el conjunto
b, ya que como estn ordenados el siguiente valor de B ser an ms grande. Luego leemos el
siguiente valor de A a(3) y lo comparamos con b(2).
Si a(3) > b(2) entonces podemos determinar que el valor de b(2) est en el conjunto B pero no
en el conjunto A. Ahora leemos B b(3).
Si a(3) = b(3) entonces el valor se encuentra en ambos conjuntos. En este caso leemos A y B y
as sucesivamente hasta que finalice alguno de los dos conjuntos.
Si un conjunto (A) termina antes que el otro (B) podemos asegurar que todos los elementos
sobrantes (de B) no estarn contenidos en el otro conjunto (A).
Luego de este anlisis podemos plantear un enunciado que le de sentido a lo anterior.
Problema 6.1
Se tienen los archivos PRESTA_2006.dat y PRESTA_2007.dat, con la informacin
correspondiente a las prestaciones que realizaron los diferentes mdicos de una clnica. Ambos
archivos estn ordenados por id_medico y tienen los siguientes campos:
id_medico (5 dgitos)
cantidad (4 dgitos)
Existe la posibilidad de que durante el ao 2007 se hayan incorporado mdicos que no
trabajaron durante 2006. Tambin pueden haber mdicos que trabajaron durante 2006 pero no
durante 2007.
Se Pide
http://holamundopascal.blogspot.mx/2007/08/capitulo6.html
19/24
15/10/2015
HolaMundo.pascal(online):Captulo6
1. Un listado de los mdicos que se incorporaron durante 2007 (no sern ms de 100).
2. Un listado de los mdicos que solo trabajaron durante 2006 (no sern ms de 100).
3. Un listado indicando los mdicos que incrementaron la cantidad de prestaciones de un
ao al otro.
Anlisis
La idea del apareo de archivos es recorrer simultaneamente ambos archivos comparando su
campo clave (por el cual estn ordenados). Si encontramos un registro en PRESTA_2006 que no
est en PRESTA_2007 corresponder a un mdico que no trabaj en 2007. Si encontramos un
registro en PRESTA_2007 que no est en PRESTA_2006 entonces ese mdico se incorpor en
2007. Si encontramos un mismo id_medico en ambos archivos entonces ese mdico trabaj en
2006 y 2007.
Veamos el siguiente ejemplo (los datos de la izquierda corresponden a PRESTA_2006. Los de la
derecha corresponden a PRESTA_2007):
http://holamundopascal.blogspot.mx/2007/08/capitulo6.html
20/24
15/10/2015
HolaMundo.pascal(online):Captulo6
Ahora en los dos archivos tenemos registros con el mismo id_medico (3). Este mdico
tambin trabaj los dos aos. Volvemos a leer ambos archivos.
La estrategia de solucin ser la siguiente: tendremos dos arrays (arr06 y arr07) de 100
elementos cada uno. En arr06 iremos guardando los mdicos que solo trabajaron en 2006
(punto 2 del enunciado). En arr07 iremos guardando los mdicos que se incorporaron a
trabajar en 2007 (punto 1 del enunciado). Los mdicos que trabajaron los dos aos e
incrementaron la cantidad de prestaciones (punto 3 del enunciado) los listaremos a medida que
los encontremos.
Veamos la seccin type para definir los tipos de datos.
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
type
//registrodelosarchivos
RPresta=record
id_medico:longint;
cantidad:integer;
end;
//tipoparalosarchivos
FPresta=fileofRPresta;
//tipoparalosarraysdemedicos
AMed=array[1..100]oflongint;
http://holamundopascal.blogspot.mx/2007/08/capitulo6.html
21/24
15/10/2015
HolaMundo.pascal(online):Captulo6
http://holamundopascal.blogspot.mx/2007/08/capitulo6.html
22/24
15/10/2015
HolaMundo.pascal(online):Captulo6
3 comentarios:
Annimo dijo...
Excelente tu trabajo en toda la pgina. Estoy cursando Algoritmos en la UTN y me
recomendaron tu pgina, la verdad me aclaraste muchas dudas con el tema de
archivos.
Hay algunos errores en los diagramas, lo cual lo veo muy til (apropsito o no) porque
me obliga a pensar y analizar si estn bien, y no nicamente a leer de corrido cada
ejercicio.
Un abrazo y segu con la pgina!
03 junio, 2008 23:28
Sebastian dijo...
Pablo veo en la parte de Indexacin de Archivos que usas un array para almacenar
DOS campos:
1 legajo
2 posArch
Luego usas ese Array para todo el ejemplo.
No tendras que usar una matriz de 2x100?
Creo que ahi tenes un error porque por mas que declares al array con un registro de
dos variables no las podes meter. O si?
Me agarro la duda...
Gracias
12 septiembre, 2008 18:33
http://holamundopascal.blogspot.mx/2007/08/capitulo6.html
23/24
15/10/2015
HolaMundo.pascal(online):Captulo6
Annimo dijo...
ola tengo una consulta...puede ser que solo pueda subir 2 campos de un registro..o sea
no el registro entero al array....a ver si me explico por ejmplo tengo
descripcion,monto,fecha,nombre en un registro de archivo..y yo solo kiero subir
descripcion y monto al array se usa la el mismo procedimiento de "subir archivo"?
25 septiembre, 2008 12:05
Entrada ms reciente
Pgina principal
Entrada antigua
http://holamundopascal.blogspot.mx/2007/08/capitulo6.html
24/24