15.6.- Las colecciones Turbo vision no es solo un conjunto de objetos para lograr un buen aspecto en nuestras aplicaciones sino que tambien permite algunas cosas mas. Ahora veremos como guardar elementos en un array que es polimorfico, donde cada elemento puede ser cualquier cosa y ademas es ampliable, nosotros tenemos que decirle los elementos y turbo vision hara la parte dificil del trabajo. En este caso es mejor poner un ejemplo y luego daremos la explicacion correspondiente. Vamos a ver un programa que lista todos los archivos en un subdirectorio, los ordena y los imprime ,todo ello como aplicacion de colecciones: PROGRAM ARCHIVOS; USES CRT,DOS,OBJECTS; TYPE PARRAY = ^TARRAY; TARRAY = OBJECT (TOBJECT) NOMBRE : PSTRING; LONGITUD : PSTRING; HORA : PSTRING; CONSTRUCTOR INIT (NOM,LON,HOR:STRING); DESTRUCTOR DONE; VIRTUAL; PROCEDURE IMPRIME; VIRTUAL; END; PORDENADO = ^TORDENADO; TORDENADO = OBJECT (TSORTEDCOLLECTION) FUNCTION KEYOF (ITEM: POINTER): POINTER; VIRTUAL; FUNCTION COMPARE (CAD1, CAD2: POINTER): INTEGER; VIRTUAL; END; FUNCTION TORDENADO.KEYOF (ITEM: POINTER): POINTER; BEGIN KEYOF := PARRAY (ITEM)^.NOMBRE; { ORDENA POR NOMBRE } END; FUNCTION TORDENADO.COMPARE (CAD1, CAD2: POINTER): INTEGER; BEGIN IF PSTRING (CAD1)^ = PSTRING (CAD2)^ THEN COMPARE := 0 ELSE IF PSTRING (CAD1)^ < PSTRING (CAD2)^ THEN COMPARE := -1 ELSE COMPARE := 1; END; CONSTRUCTOR TARRAY.INIT (NOM,LON,HOR:STRING); BEGIN NOMBRE := NEWSTR (NOM); LONGITUD := NEWSTR (LON); { TODO A PUNTEROS A STRING } HORA := NEWSTR (HOR); END; DESTRUCTOR TARRAY.DONE; BEGIN DISPOSESTR (NOMBRE); DISPOSESTR (LONGITUD); { ELIMINA TODOS LOS DATOS } DISPOSESTR (HORA); END; PROCEDURE TARRAY.IMPRIME; VAR A : INTEGER; FECHA : DATETIME; CONV : LONGINT; BEGIN WRITE (NOMBRE^); GOTOXY (20,WHEREY); WRITE (HORA^); GOTOXY (32,WHEREY); VAL (LONGITUD^,CONV,A); UNPACKTIME (CONV,FECHA); WRITE (FECHA.YEAR,'/',FECHA.MONTH,'/',FECHA.DAY, ' ',FECHA.HOUR,':',FECHA.MIN); WRITELN; END; PROCEDURE IMPRESION (COLECTA: PCOLLECTION); PROCEDURE IMPRIMIR (PUNTERO:PARRAY);FAR; BEGIN PUNTERO^.IMPRIME; { LLAMA AL QUE IMPRIME } END; BEGIN WRITELN; WRITELN('LISTA DE FILES EN EL SUBDIRECTORIO:'); WRITELN; WRITELN ('NOMBRE LONGITUD FECHA HORA'); WRITELN; COLECTA^.FOREACH (@IMPRIMIR); { IMPRIME TODOS } END; PROCEDURE BUSCA_NOMBRE (COLECTA:PCOLLECTION;ARCHIVO:STRING); FUNCTION BUSCA (LISTA:PARRAY):BOOLEAN;FAR; BEGIN BUSCA := POS (ARCHIVO,LISTA^.NOMBRE^) <> 0; END; VAR BUSQUEDA : PARRAY; BEGIN { BUSCA EL PRIMERO QUE APAREZCA } WRITELN; BUSQUEDA := COLECTA^.FIRSTTHAT (@BUSCA); IF BUSQUEDA = NIL THEN WRITELN ('NO EXISTE EL ARCHIVO') ELSE BEGIN WRITELN('ARCHIVO ENCONTRADO:'); BUSQUEDA^.IMPRIME; END; END; VAR LISTA_DE_ARCHIVOS : PORDENADO; INFORMACION : SEARCHREC; CAD1,CAD2 : STRING; BEGIN CLRSCR; LISTA_DE_ARCHIVOS := NEW (PORDENADO,INIT(50,20)); WITH LISTA_DE_ARCHIVOS^ DO BEGIN FINDFIRST ('A:\*.*',ARCHIVE,INFORMACION); STR (INFORMACION.TIME,CAD1); STR (INFORMACION.SIZE,CAD2); INSERT (NEW (PARRAY,INIT (INFORMACION.NAME,CAD1,CAD2))); WHILE DOSERROR = 0 DO BEGIN FINDNEXT(INFORMACION); STR (INFORMACION.TIME,CAD1); STR (INFORMACION.SIZE,CAD2); INSERT (NEW (PARRAY,INIT (INFORMACION.NAME,CAD1,CAD2))); END; END; IMPRESION (LISTA_DE_ARCHIVOS); BUSCA_NOMBRE (LISTA_DE_ARCHIVOS,'LANPRU.PAS'); DISPOSE(LISTA_DE_ARCHIVOS,DONE); END. Ante todo hay que aclarar que en el programa se usa la coleccion ordenada, en contraposicion de la coleccion comun que no ordena sus elementos. La coleccion ordenada normalmente rechaza los elementos repetidos (puede cambiarse) y hace una ordenacion de los elementos, ademas cuando se quiera encontrar algo se realiza la busqueda binaria, pero tiene la desventaja de que todos los elementos deben ser iguales. El programa empieza declarando un descendiente de tobject, heredando toda la funcionalidad de este, asi a este solo hay que indicarle los datos que vamos a usar, el constructor se encarga de convertir las cadenas pasadas en punteros, el destructor se encarga de la eliminacion de ellos y ademas se aniade un procedimiento de impresion para visualizar los resultados. Lo siguiente que se crea es un objeto derivado de coleccion ordenada se suministra una funcion para saber cual de elementos se quiere comparar (keyof), y la que los compara (compare). Lo dificil viene luego de tarray.imprime. Observe el procedimiento impresion existe un procedimiento aniadido en el llamado imprimir. Este debe ser declarado lejano (far) y debe llamar al procedimiento que verdaderamente realiza la impresion de un elemento. El foreach colocado en la parte principal del procedimiento debe contener la direccion del procedimiento declarado un poco mas arriba lo cual hara el trabajo pero para todos los elementos. Lo mismo pasa con el procedimiento busca_nombre pero en este caso se usa el procedimiento firstthat que encuentra la primera aparicion de lo que se le indica, en este caso el nombre del archivo (LANPRU.PAS), el resto es una sencilla busqueda de archivos realizada con findfirst y findnext en la unidad dos. .