Elementos de Programación / 2000 / Prof. Carlos Iván Chesñevar 1 Un ejemplo del uso de Punteros: manejo de cantantes Un diskjockey desea contar con un programa que permita manejar información sobre cantantes. Desea manejar información sobre varios cantantes. A cada cantante le asigna un número que lo identifica (ej: entre 1 y 1000). Algunos cantantes –en opinión del diskjockeytienen identificado un mejor tema, y en tal caso el diskjockey desea guardar la cadena correspondiente al nombre de dicho tema. Escribir un programa que permita manejar la información que desea el diskjockey. La información se deberá cargar en una tabla. El programa deberá también permitir transferir la tabla a un archivo y viceversa. Ejercicios adicionales: a) Modifique el programa anterior para permitir eliminar cantantes de la tabla. Cuidado: puede ser necesiario utilizar dos veces la sentencia dispose, aunque no siempre, para eliminar a un cantante de la tabla (por qué?). b) Escriba un procedimiento GenerarArchivoTemas que genere un archivo de texto Temas.txt. Dicho archivo de texto contendrá el nombre de todos los cantantes que tienen un mejor tema conocido. Su archivo deberá tener una apariencia como la siguiente: NOMBRE Marcela Morelo Noelia Britney Spears Shakira Cheyenne … TEMA Ponernos de acuerdo Candela I did it again Ojos así (No se conoce tema) .... c) Escriba otro procedimiento MostrarArchivoTemas que permita mostrar el archivo anterior por pantalla. Program P; { Programa para manejo de datos de cantantes } Const TopeTabla = 1000; Type TOpcion = 1..5; TCadena = string; TMejorTema = TCadena; {opciones disponibles} {cadena de caracteres de longitud arbitraria} {los temas son cadenas} TCantante = Record {por cada cantante, guardamos nombre y mejor tema} Nombre: TCadena; MejorTema: ^TMejorTema; End; TPunCantante = ^TCantante; TIndiceTabla = 1..TopeTabla; { Datos de un cantante para almacenar en un archivo } TDatosDeCantante = Record NroCantante : TIndiceTabla; Nombre,MejorTema:TCadena; End; Elementos de Programación / 2000 / Prof. Carlos Iván Chesñevar { Tabla de cantantes } TTablaCantantes = Record Datos: Array [1..TopeTabla] of TPunCantante; UltimoCantanteIngresado:0..TopeTabla; End; { Archivo de cantantes } TArchivoCantantes = File of TDatosDeCantante; Var T: TTablaCantantes; A: TArchivoCantantes; Opcion:TOpcion; {..............................................} Procedure InicializarTabla(Var T:TTablaCantantes); { Dada una tabla T, inicializa el contenido con valor nil, para todos los cantantes posibles.} Var i:TIndiceTabla; Begin T.UltimoCantanteIngresado:=0; For i:=1 to TopeTabla do T.Datos[i]:=nil; End; {..............................................} Procedure CargarCantante(Var C:TCantante); { Dado un registro C:TCantante, permite al usuario cargar sus campos. Notese que el mejor tema es un puntero a una cadena, y el valor de dicho puntero es nil en caso de que no haya un mejor tema asociado a C} Var Tema:TCadena; Begin write('Nombre:'); readln(C.Nombre); write('Mejor tema? (0=no tengo preferencia): '); readln(Tema); If Tema<>'0' then begin new(C.MejorTema); C.MejorTema^:=Tema; end else C.MejorTema := nil; End; {............................................} Procedure InsertarCantante(Var T:TTablaCantantes); { Permite agregar un nuevo cantante en la tabla T; el cantante se aniade siempre al final de la tabla } Var i:TIndiceTabla; Begin If T.UltimoCantanteIngresado < TopeTabla then Begin T.UltimoCantanteIngresado := T.UltimoCantanteIngresado+1; i := T.UltimoCantanteIngresado; writeln('Ingrese los datos de un cantante:'); 2 Elementos de Programación / 2000 / Prof. Carlos Iván Chesñevar new(T.Datos[i]); CargarCantante(T.Datos[i]^); End else writeln('Tabla llena!'); End; {............................................} Procedure MostrarMejoresTemas(Var T:TTablaCantantes); { recorre toda la tabla T, y muestra los nombres de los cantantes en la tabla, y sus mejores temas, si existen } Var i:TIndiceTabla; Begin For i:=1to T.UltimoCantanteIngresado do Begin If T.Datos[i]<>nil then With T.Datos[i]^ do begin writeln('**************************************'); writeln('Cantante ',i); write('Nombre:'); writeln(Nombre); write('Mejor tema:'); If T.Datos[i]^.MejorTema = nil then writeln('No se conoce mejor tema') else writeln(T.Datos[i]^.MejorTema^); end; End; End; {........................................................} Procedure Pasar_tabla_a_archivo(Var T:TTablaCantantes; Var A:TArchivoCantantes); { Este procedimiento transfiere todos los datos de T a un archivo A. Notese que se realiza una "transformacion" que copia el contenido de las componentes de T en registros de tipo TDatosDeCantante, los cuales se guardan en A} Var DatosDeCantante:TDatosDeCantante; i : TIndiceTabla; Begin rewrite(A); For i:=1 to T.UltimoCantanteIngresado do Begin If T.Datos[i]<>nil then begin DatosDeCantante.NroCantante:=i; DatosDeCantante.Nombre := T.Datos[i]^.Nombre; If T.Datos[i]^.MejorTema<>nil then DatosDeCantante.MejorTema := T.Datos[i]^.MejorTema^ else DatosDeCantante.MejorTema :='@'; write(A,DatosDeCantante); end; 3 Elementos de Programación / 2000 / Prof. Carlos Iván Chesñevar End; close(A); End; {............................................................} Procedure Pasar_archivo_a_tabla(Var T:TTablaCantantes; Var A:TArchivoCantantes); { Este procedimiento transfiere el contenido del archivo A a la tabla T. Notese que el valor de T.UltimoCantanteIngresado sera el valor mas grande de entre los nros. de cantantes que aparezcan en A} Var DatosDeCantante:TDatosDeCantante; MaximoNroCantante:0..TopeTabla; i : TIndiceTabla; Begin reset(A); InicializarTabla(T); MaximoNroCantante:=0; while not eof(A) do begin read(A,DatosDeCantante); If DatosDeCantante.NroCantante > MaximoNroCantante then MaximoNroCantante := DatosDeCantante.NroCantante; i := DatosDeCantante.NroCantante; { i = nro. del cantante} new( T.Datos[i] ); {se crea un registro en pos. i-esima de T} With T.Datos[i]^ do begin Nombre := DatosDeCantante.Nombre; {se guarda el nombre} If DatosDeCantante.MejorTema <>'@' { y si existe un mejor tema} then begin {se crea un puntero a una cadena} new(T.Datos[i]^.MejorTema); { y en dicha cadena se almacena el nombre del mejor tema} T.Datos[i]^.MejorTema^:=DatosDeCantante.MejorTema; end else T.Datos[i]^.MejorTema:=nil end; end; T.UltimoCantanteIngresado := MaximoNroCantante; End; {............................................} Procedure Menu(Var Opcion:TOpcion); { Este procedimiento simplemente permite al usuario elegir de entre varias opciones disponibles, mostrando los carteles apropiados } Begin writeln('--------------------------------------- '); writeln(' Manejo de Cantantes '); writeln('--------------------------------------- '); writeln; writeln('1) Insertar nuevo cantante'); writeln('2) Mostrar mejores temas'); writeln('3) Pasar tabla a un archivo'); 4 Elementos de Programación / 2000 / Prof. Carlos Iván Chesñevar writeln('4) Pasar archivo a una tabla'); writeln('5) Salir'); write('Su opcion:'); readln(Opcion); End; { ..........................................................} Begin {ppal} assign(A,'c:\canta.dat'); Repeat Menu(Opcion); Case Opcion of 1 : InsertarCantante(T); 2 : MostrarMejoresTemas(T); 3 : begin writeln('Su tabla sera almacenada en un archivo'); writeln('y se destruira el contenido preexistente de'); writeln('dicho archivo...'); Pasar_tabla_a_archivo(T,A); end; 4 : begin writeln('Su tabla actual sera cargada con informacion'); writeln('de un archivo.. los datos actuales de la tabla'); writeln('se borraran'); Pasar_archivo_a_tabla(T,A); end; end; Until Opcion=5; {salir} End. 5