Universidad Politécnica de Madrid Escuela Universitaria de Informática Departamento de Lenguajes, Proyectos y Sistemas Informáticos Asignatura PROGRAMACIÓN II EXAMEN DE LA CONVOCTORIA DE SEPTIEMBRE Plan: 92 / Curso: 2000-2001 Madrid a 18 de Septiembre de 2001 APELLIDOS: .................................. NOMBRE: ................................................. Nº DE MATRÍCULA: ........ DNI:................. GRUPO: ......................................... CALIFICACIONES TEORÍA PROB_1 PROB_2 TOTAL CUESTIONES TEÓRICAS Valoración: 3 puntos. Pregunta correcta:....................................0'2 puntos. Pregunta no contestada o incorrecta: .... -0'15 puntos I. PROGRAMACIÓN CONCURRENTE. 1. ¿En qué arquitecturas no es directamente aplicable el modelo de variables compartidas?. En las arquitecturas distribuidas 2. Explica los problemas que pueden surgir en el anidamiento de llamadas a monitores. La situación puede explicarse de la forma siguiente: Un proceso P1, entra en un Monitor A para ejecutar un procedimiento, en ese procedimiento se produce una llamada a un procedimiento de otro monitor B. Simultáneamente otro proceso P2 entra a ejecutar un procedimiento del monitor B y desde ese procedimiento se produce una llamada a un procedimiento del monitor A. En esta situación, si los procesos mantienen la exclusión mutua de los monitores, se produce un interbloqueo de procesos. Página 1 de 10 Programación II Septiembre 2001 3. ¿Qué ventajas proporcionan los monitores frente a los semáforos?. Mayor estructuración del código, ya que los accesos a las variables compartidas se reunen en el código de los monitores. Mayor seguridad ya que el acceso a las variables del monitor está garantizado, por el propio monitor, que se realiza bajo exclusión mutua 4. ¿En qué consiste el problema de la exclusión mutua selectiva?. Pon un ejemplo de problema de esta clase y justifica la respuesta. En los problemas de exclusión mutua selectiva, cada proceso compite por sus recursos no con todos los demás procesos sino con un subconjunto de ellos. Dos casos típicos de dicha competencia se producen cuando los procesos compiten por los recursos según su tipo de proceso o por su proximidad. Ejemplos de Exclusión mutua selectiva son: El problema de los filósofos y el problema de los lectores y escritores. 5. ¿Cuál es la política utilizada para liberar un proceso mediante RESUME en un Monitor de PASCAL-FC? La política seguida por Pascal_FC es la que se conoce con el nombre de reanudación inmediata. El proceso que ejecuta una operación RESUME sobre una variable de tipo CONDITION del monitor, cede la exclusión mutua del monitor al proceso que acaba de liberar, en el caso de que exista un proceso bloqueado en la susodicha CONDITION, pasando a una cola de ALTA PRIORIDAD; si la cola de la variable CONDITION está vacía, el proceso continua su ejecución en el procedimiento del monitor. II. PROGRAMACIÓN ORIENTADA A OBJETOS. 6. Programáticamente, ¿cómo se establece una relación de asociación entre una clase cliente y otra clase servidor en PIIPOO? La clase cliente tiene como atributo un puntero a un objeto de la clase servidor. 7. ¿Qué características diferencian una relación de uso de una relación de asociación en POO?. Visibilidad pública en las dos relaciones, aunque en la de uso puede ser privada. Versatilidad total en la de uso mientras que en la de Asociación es poco versátil. Temporalidad poco duradera en la de uso mientras que en la de asociación es duradera. Página 2 de 10 Programación II 8. En la relación de herencia del gráfico de la izquierda, ¿es posible que la clase cA no sea una clase abstracta y sin embargo que la clase cC sí lo sea? Razone la respuesta. cA cB Septiembre 2001 cC cD Sí, la clase cC puede añadir un nuevo método diferido o redefinir un método heredado de su clase padre como diferido. En este caso, la clase cC es abstracta. 9. ¿En qué se diferencia la ley estricta de la ley flexible de Demeter? En la ley flexible de Demeter está permitido el acceso a los atributos heredados de la clase padre en la implantación de los métodos de la clase. En la ley estricta de Demeter no se puede acceder a los atributos heredados de la clase padre. 10. Dado el siguiente código: CLASS INTERFACE cX PUBLIC METHODS OPERATOR := (pX : ^cX); END CLASS INTERFACE cX CLASS INTERFACE cY INHERITS FROM cX PUBLIC METHODS OPERATOR := (pY : ^cY); END CLASS INTERFACE cY … p : ^cX; q : ^cY; … p^ := q; q^ := p; (*A*) (*B*) ¿Son válidas las dos asignaciones (*A*) y (*B*)? Razone la respuesta. (*A*) No es válida porque el método de asignación de la clase cX espera un puntero a un objeto de la clase cX y le llega un puntero a un objeto de la clase cY. (*B*) sí es válida porque la clase cY tiene sobrecargado el operador de asignación, en este caso se ejecuta el método heredado de su clase padre que recibe como parámetro un puntero a un objeto de la clase cX Página 3 de 10 Programación II III. Septiembre 2001 PROGRAMACIÓN FUNCIONAL. 11. ¿Es correcta la definición de la siguiente función? En caso afirmativo, escriba su tipo y describa qué hace mediante un ejemplo. let rec f = function [ ] -> [ ] | cab::cola -> (hd cab, tl cab):: f cola;; La función es correcta y su tipo es: ‘a list list -> (‘a * ‘a list) list. Lo que hace es transformar una lista de listas de cualquier tipo en una lista de tuplas del tipo: ‘a * ’a list f [[1; 3;4]; [2]];; ‘a * ‘a list = [(1, [3; 4]); (2, [ ])] 12. Indíquese para cada una de las siguientes tuplas si corresponden a una posible expresión, a un posible patrón, ambas cosas o ninguna: 1) (4, _) 1) Un patrón. 2) (4, 0) 3) (4>0, 0) 2) Un patrón y una posible expresión. 3) Una posible expresión. 13. Defina tipo y sistema de tipos Un tipo es un conjunto de los posibles valores de datos que pertenecen a dicho tipo. Sistema de tipos es un conjunto de reglas que determina el tipo para cada uno de los valores de datos que entran en juego en un programa y las reglas de compatibilidad entre los distintos tipos del lenguaje de programación. 14. ¿Existe un patrón que se corresponda con listas de enteros con longitudes entre 2 y 3 elementos? No existe tal patrón. CAML no permite definir este tipo de patrones. 15. Describa en qué consiste la técnica de reducción y en qué casos es aplicable Esta técnica consiste en utilizar la cabeza de una lista como acumulador del resultado final de la función recursiva. Para poder aplicar esta técnica el tipo de la función debe ser ‘a list -> ‘a. Página 4 de 10 Programación II Septiembre 2001 Universidad Politécnica de Madrid Escuela Universitaria de Informática Departamento de Lenguajes, Proyectos y Sistemas Informáticos Asignatura PROGRAMACIÓN II ENUNCIADOS DE LOS PROBLEMAS DEL EXAMEN DE LA CONVOCATORIA DE SEPTIEMBRE Plan: 92 / Curso: 2000-2001 Madrid a 18 de Septiembre de 2001 Fechas de Publicación de Notas y de Revisión de Exámenes Publicación de Notas Miércoles 26 de Septiembre de 2001 Revisión de Examen y Prácticas: Viernes 28 de Septiembre de 2001 en horario que será publicado en el tablón de la Asignatura a la publicación de las notas Puede consultar sus notas en: www.lpsi.eui.upm.es/ProgramacionII/Notas.htm PROBLEMA 1: PROGRAMACION CONCURRENTE Puntuación: 2'5 puntos El responsable de la asignatura de Programación II ha codificado el siguiente programa que recoge por teclado los datos de los alumnos (nombre, notas de prácticas de concurrencia y objetos y del examen) y, posteriormente, imprime por pantalla únicamente el nombre y nota final de aquellos aprobados en la asignatura: program listadoAprobados; const maxCar=10; maxAlu=100; type tAlumno=record nombre:array [1..maxCar] of char; prpc, prpoo, ex:integer; aprob:boolean; nota:integer; end; tAlumnos=array [1..maxAlu] of tAlumno; procedure rellenar (var alumnos:tAlumnos); var i:integer; begin for i:=1 to maxAlu do begin readln(alumnos[i].nombre); readln (alumnos[i].prpc); readln (alumnos[i].prpoo); readln (alumnos[i].ex); readln (alumnos[i].aprob); end; end; procedure aprobar (var alumno:tAlumno); begin alumno.aprob:=(alumno.prpc>=5)and (alumno.prpoo>=5) and (alumno.ex>=5); end; Página 5 de 10 Programación II Septiembre 2001 procedure calificar (var alumno:tAlumno); begin alumno.nota:=(alumno.prpc+alumno.prpoo + alumno.ex*8)div 10; end; procedure visualizar (alumno:tAlumno); begin write (alumno.prpc,' '); write (alumno.prpoo,' '); write (alumno.ex,' '); writeln (alumno.nota); end; var alumnos:tAlumnos; begin rellenar(alumnos); for i:=1 to maxAlu do begin Aprobar(alumnos[i]); if alumnos[i].aprob then begin Calificar(alumnos[i]); Visualizar(alumnos[i]); end end end. Como es lógico, el profesor más joven de la asignatura corrige los achaques del maduro responsable indicando la innecesaria secuencialización de aprobar, calificar y visualizar para cada uno de los alumnos frente a la potencial paralelización de aprobar a uno, mientras se califica a otro y se visualiza un tercero. Para asistir al maduro responsable se pide codificar un programa concurrente que respete la funcionalidad del programa anterior bajo las siguientes condiciones: Permitir la actualización del campo aprobado de un alumno en paralelo con el cálculo de la nota final de otros alumnos (supuestamente aprobado) y en paralelo con la visualización de un tercer alumno (supuestamente aprobado) mediante los tres procesos Aprobador, Calificador y Visualizador respectivamente. Sincronizar el progreso del proceso Calificador supeditado al progreso del proceso Aprobador (calificando únicamente a alumnos previamente aprobados) y sincronizar el progreso del proceso Visualizador supeditado al progreso del proceso Calificador (visualizando únicamente a alumnos previamente aprobados y calificados). NOTA. La solución precisa únicamente la codificación correspondiente a las herramientas de concurrencia escogidas (semaforos o monitores), los procesos y el cuerpo del programa principal. La solución NO precisa la recodificación correspondiente a las constantes, tipos, subprogramas y variables globales del código anterior pero SI la indicación de su situación dentro de la solución. Página 6 de 10 Programación II Septiembre 2001 SOLUCIÓN: PROCESS Aprobador (VAR Alumnos: tAlumnos; VAR sAprobar : SEMAPHORE); VAR i: INTEGER; BEGIN FOR i:=1 TO MaxAlu DO BEGIN Aprobar(Alumnos[i]); SIGNAL(sAprobar) END END; PROCESS Calificador (VAR Alumnos: tAlumnos; VAR sAprobar, sCalificar: SEMAPHORE); VAR i: INTEGER; BEGIN FOR i:=1 TO MaxAlu DO BEJÍN WAIT(sAprobar); IF Alumnos[I].Aprob THEN Calificar(Alumnos[i]); SIGNAL(sCalificar) END END; PROCESS Visualizador (VAR Alumnos: tAlumnos; VAR sCalificar: SEMAPHORE); VAR i: INTEGER; BEGIN FOR i:=1 TO MaxAlu DO BEJÍN WAIT(sCalificar); IF Alumnos[I].Aprob THEN Visualizar(Alumnos[i]); END END; (*PROGRAMA PRINCIPAL*) VAR Alumnos:tAlumnos; sAprobar, sCalificar: SEMAPHORE; BEGIN INITIAL(sAprobar, 0); INITIAL(sCalificar, 0); Rellenar(Alumnos); COBEGIN Aprobador(Alumnos, sAprobar); Calificador(Alumnos, sAprobar, sCalificar); Visualizador(Alumnos, sCalificar) COEND END. Página 7 de 10 Programación II PROBLEMA 2: PROGRAMACIÓN ORIENTADA A OBJETOS Septiembre 2001 Puntuación: 2'5 puntos La última versión del lenguaje PIIPOO proporciona la clase TEXTFILE para tratar ficheros de texto. El interfaz de esta clase es el siguiente: CLASS INTERFACE CTEXTFILE; PUBLIC METHODS (* recibe la ruta del fichero *) CONSTRUCTOR CTEXTFILE (strFichero : STRING); DESTRUCTOR CTEXTFILE; PROCEDURE RESET; PROCEDURE READLN (VAR strLinea : STRING); FUNCTION EOF : BOOLEAN; PROCEDURE REWRITE; PROCEDURE WRITELN (strLinea : STRING); END CLASS INTERFACE CTEXTFILE; Además se conoce de la existencia del siguiente método privado, que se usa para la construcción del fichero a partir de su ruta: CLASS IMPLEMENTATION CTEXTFILE; PRIVATE METHODS PROCEDURE ASSIGN (strFichero : STRING); END CLASS IMPLEMENTATION CTEXTFILE; Actualmente se pretende tratar con ficheros de texto cifrados, para lo que se ha establecido el siguiente interfaz de un cifrador de texto abstracto: CLASS INTERFACE CCifradorTexto; PUBLIC METHODS DEFERRED PROCEDURE Cifrar (VAR strTexto : STRING); DEFERRED PROCEDURE Descifrar (VAR strTexto : STRING); END CLASS INTERFACE CCifradorTexto; Se pide: 1) Escribir el interfaz y la implementación de la clase CFicheroTextoCifrado, que especialice la clase CTEXTFILE para leer y escribir ficheros de texto redefiniendo las siguientes funciones: a) El constructor recibirá la ruta del fichero y un cifrador polimórfico que implanta el interfaz CCifradorTexto. b) READLN debe leer la línea del fichero y después descifrar la linea leída usando su cifrador. c) WRITELN debe cifrar la línea a escribir usando su cifrador.y después escribirla en el fichero. 2) Escribir el interfaz y la implementación de un cifrador de texto CCifradorCesar que implemente: a) Constructor que recibirá un desplazamiento mediante un entero. b) Cifrar aplicará este desplazamiento en módulo 256 a todos los caracteres del texto a cifrar, sumandolo al ordinal de cada carácter. c) Descifrar deshará el desplazamiento en módulo 256 en todos los caracteres del texto a descifrar, restandolo al ordinal de cada carácter. 3) Escribir el método de una clase CGestorFicheros: a) Copiar, que copie un fichero de texto origen de cualquier clase en otro fichero de texto destino de cualquier clase (ya sean ficheros cifrados o no). Para ello preparará el fichero origen para lectura, el destino para escritura, y leerá línea por línea el fichero origen y las escribirá en el fichero destino. Página 8 de 10 Programación II Septiembre 2001 CLASS INTERFACE CgestorFicheros PUBLIC METHODS PROCEDURE Copiar (pFicheroOrigen : POLYMORPHIC ^TEXTFILE; pFicheroOrigen : POLYMORPHIC ^TEXTFILE); END CLASS INTERFACE CgestorFicheros Para resolver el problema se dispone de las clases primitivas de PIIPOO. Algunas definiciones útiles de estas clases se presentan a continuación: CLASS INTERFACE STRING; PUBLIC METHODS FUNCTION GETAT (iPosicion : INTEGER) : CHAR; PROCEDURE PUTAT (iPosicion : INTEGER; c : CHAR); END CLASS INTERFACE STRING; CLASS INTERFACE INTEGER; PUBLIC METHODS FUNCTION CHR : CHAR; (* Devuelve el caracter con este ordinal *) END CLASS INTERFACE INTEGER; CLASS INTERFACE CHAR; PUBLIC METHODS FUNCTION ORD : INTEGER; (* Devuelve el ordinal del caracter *) END CLASS INTERFACE CHAR; SOLUCIÓN (* Apartado 1 *) CLASS INTERFACE CFicheroTextoCifrado; INHERITS FROM CTEXTFILE; PUBLIC METHODS CONSTRUCTOR CFicheroTextoCifrado (strFichero : STRING; strClave : STRING; pCifrador : POLYMORPHIC ^CCifradorTexto); REDEFINED PROCEDURE READLN (VAR strLinea : STRING); REDEFINED PROCEDURE WRITELN (strLinea : STRING); END CLASS INTERFACE CFicheroTextoCifrado; CLASS IMPLEMENTATION CFicheroTextoCifrado; ATTRIBUTES mpCifrador : POLYMORPHIC ^CCifradorTexto; METHODS DEFINITION CONSTRUCTOR CFicheroTextoCifrado (strFichero : STRING; strClave : STRING; pCifrador : POLYMORPHIC ^CCifradorTexto); BEGIN SELF.ASSIGN(strFichero); mpCifrador := pCifrador; END; PROCEDURE READLN (VAR strLinea : STRING); BEGIN SUPER.READLN(strLinea); mpCifrador^.Descifrar(strLinea) END; PROCEDURE WRITELN (strLinea : STRING); BEGIN mpCifrador^.Cifrar(strLinea); SUPER.WRITELN(strLinea) END; END CLASS IMPLEMENTATION CFicheroTextoCifrado; Página 9 de 10 Programación II Septiembre 2001 (* Apartado 2 *) CLASS INTERFACE CCifradorTextoSimple; INHERITS FROM CCifradorTexto; PUBLIC METHODS REDEFINED PROCEDURE Cifrar (strClave : STRING; VAR strTexto : STRING); REDEFINED PROCEDURE Descifrar (strClave : STRING; VAR strTexto : STRING); END CLASS INTERFACE CCifradorTextoSimple; CLASS IMPLEMENTATION CCifradorTextoSimple; ATTRIBUTES miDesplazamiento: INTEGER; METHODS DEFINITION CONSTRUCTOR CCifradorTextoSimple (desplazamiento : INTEGER); BEGIN miDesplazamiento := desplazamiento; END; PROCEDURE Cifrar (VAR strTexto : STRING); VAR i : INTEGER; c : CHAR; BEGIN FOR i := 1 TO strTexto.LENGTH DO BEGIN c := strTexto.GETCHAR(i); c := ((c.ORD + miDesplazamiento) MOD 256).CHR; strTexto.PUTCHAR(i, c) END END; PROCEDURE Descifrar (VAR strTexto : STRING); VAR i : INTEGER; c : CHAR; BEGIN FOR i := 1 TO strTexto.LENGTH DO BEGIN c := strTexto.GETAT(i); c := ((c.ORD - miDesplazamiento) MOD 256).CHR; strTexto.PUTAT(i, c) END END; CLASS IMPLEMENTATION CCifradorTextoSimple; (* Apartado 3 *) PROCEDURE Copiar (pFicheroOrigen : POLYMORPHIC ^TEXTFILE; pFicheroOrigen : POLYMORPHIC ^TEXTFILE); VAR strLinea : STRING; BEGIN pFicheroOrigen^.RESET; pFicheroDestino^.REWRITE; WHILE NOT pFicheroOrigen^.EOF DO BEGIN pFicheroOrigen^.READLN(strLinea); pFicheroDestino^.WRITELN(strLinea) END END; Página 10 de 10