CEUS IP2 Examen 2 de 25-MAYO-2004 Gualberto Asencio Cortés PARTES, PUNTOS Y TIEMPO PARTE PRIMERA: A. B. C. D. E. F. Lenguaje Java y Arrays Orientación a objetos y String Interfaces Herencia Clone Excepciones PARTE SEGUNDA: G. H. I. J. Listas Collections Iteradores Comparadores 6p 58 min 1.33 p 1.33 p 0.66 p 0.66 p 1.00 p 1.00 p 15 min 15 min 05 min 05 min 08 min 10 min 4p 43 min 1.33 p 0.66 p 1.00 p 1.00 p 13 min 08 min 10 min 12 min PARTE PRIMERA: A. Lenguaje Java y Arrays 1) Se trata de hacer un programa para que lea del teclado el número de filas y columnas de una matriz de números enteros. A continuación el programa rellenará automáticamente la matriz con los números primos a partir de 2 distribuidos ordenadamente por filas y columnas. Acto seguido la presentará en la pantalla. Escriba una clase pública MatricesPrimos que contenga un método main, otro llamado rellenaMatriz, otro obtenerPrimoMayorQue y otro presentaMatriz. Piense en sus prototipos y en cómo unos usan otros. En este caso, la tabla (matriz) tendrá el mismo número físico y lógico de elementos, es decir, se rellenará entera. La tabla se creará, lógicamente, después de conocer sus dimensiones, después de la lectura desde el teclado, esto se hará en el main. Use para dicha lectura el paquete entsal, por lo que añada lo necesario. Recuerde que todos los métodos serán estáticos pues el main también lo es. Escriba la clase completa. 1 de 9 B. Orientación a objetos y String 2) Se trata de implementar una clase que manipule las palabras contenidas en una oración, de forma que se pueda consultar la palabra i-ésima de la oración y añadir o borrar palabras. La clase se llamará Oración y tendrá los siguientes atributos ( - significa privado, * significa protegido y + significa público, esa es la notación de UML para las visibilidades): * String texto * int npalab // Es la oración // Número de palabras en el texto Los métodos de la clase serán los siguientes: + Oración (String) * * + + + + // Constructor que almacena la oración en el atributo texto y // llama a contarPalabras para inicializar el atributo npalab. void contarPalabras () // Cuenta las palabras en el atributo texto y guarda el número // en el atributo npalab. int [] posicionPalabra (int i) // Devuelve la posición en texto (empezando en 0) donde está // el primer carácter de la palabra i-ésima (o -1 si no la hay) // en el elto 0 del vector devuelto, en el 1 está la posición final String obtener (int i) // Obtiene la palabra i-ésima en la oración. Si el índice i no es // válido, devuelve una cadena vacía (“”). void insertar (String x, int i) // Inserta la palabra en el lugar de la palabra i-ésima de la // oración, desplazando ésta a la derecha. String borrar (int i) // Elimina la palabra i-ésima en la oración y la devuelve int numPalabras () // Obtiene el número de palabras en la oración Pistas (Sólo leer en caso de necesidad y parar de leer si se puede seguir sin ellas).1. Los métodos obtener, insertar y borrar usarán el método privado posicionPalabra. 2. Prácticamente casi todos los métodos usarán el método “char charAt (int i)” de la clase String para ir obteniendo los caracteres uno a uno de ‘texto’. 3. Para saber el número de caracteres (que NO el número de palabras) de un String se usará el método “int length ()”. 4. Para insertar, sería interesante sustituir ‘texto’ con el resultado de la concatenación de la subcadena desde el primer carácter de ‘texto’ hasta el carácter antes de la palabra i-ésima (que es un espacio, salvo para la primera, tenerlo en cuenta), la cadena x a insertar y la subcadena desde el carácter anterior a la palabra i-ésima (un espacio o puede que no) hasta el final de ‘texto’. Así: Insertar “hola” en la palabra 2 de “Soy amigo y no lo soy” es “Soy “ + “hola” + “ amigo y no lo soy”. 5. Para concatenar cadenas basta usar el operador +. 6. Para obtener una subcadena de i a j en la cadena ‘texto’ es “texto.substring(i,j);”. 7. Para borrar, basta con concatenar lo anterior a la palabra a eliminar con lo que venga después de la palabra a eliminar. 8. Cuidado con los índices, todos empiezan en 0, salvo el del número de palabra en la oración que empieza en 1. C. Interfaces 3) Construya una interfaz Tokenizer que contenga todos los métodos públicos (salvo el constructor, los constructores no se incluyen en las interfaces) de la clase Oración. Haga que la clase Oración implemente la interfaz Tokenizer. Por cultura, cada palabra en una cadena de caracteres se llama token, de hecho, dado su frecuente uso, Java incorpora una clase StringTokenizer que está en el paquete java.util con ventajas e inconvenientes con respecto a nuestra clase Oración. 2 de 9 D. Herencia 4) Implemente una clase OraciónPersonalizada que herede de la clase Oración. Esta clase debe tener la misma funcionalidad que Oración, sólo que el delimitador entre palabras en lugar de ser un espacio, que sea un carácter que se desee, al suministrárselo al constructor (que hay que codificar). De esta forma, se podrá crear un objeto oracion, para separar con comas las palabras, de este modo: OraciónPersonalizada oracion = new OraciónPersonalizada(“Hola,Pepe”, ‘,’); La clase tendrá un nuevo atributo: * char delimitador Redefina (reescriba) los métodos que considere oportuno. E. Clone 5) Añada un método clone tanto para la clase Oración como para OraciónPersonalizada. Sería interesante usar el método clone de Object para hacer una clonación superficial previa. No olvide declarar las clases entonces como que implementan la interfaz Cloneable. F. Excepciones Recuerde, lo que necesita saber para hacer un ejercicio de lanzamiento de excepciones es: • Nombre de la excepción • Método donde se lanza (throw) y propaga (throws) • Condición de lanzamiento 6) Añada una excepción PalabraNoEncontradaException para el método obtener de la clase Oración. Ésta se elevará en dicho método si el índice pasado como parámetro no corresponde con ninguna palabra, es decir, i < 0 ó i > número de palabras. 7) Añada una excepción DelimitadorNoVálidoException para el constructor de la clase OraciónPersonalizada. Ésta se elevará en dicho método si el delimitador pasado como parámetro no es ‘ ’ ni ‘.’ ni ‘,’ ni ‘;’. Para los ejercicios de captura de excepciones necesita saber: • En qué método se captura la excepción • Cuál es el método propagador de excepciones al que se invoca • Qué excepción hay que tratar • Encerrar el código problemático (el que llama al método propagador) con try • Qué hacer cuando se produzca (catch) 8) Escriba un método (da igual en qué clase esté) llamado “void pruebaOraciones ()” en el que se crea un objeto de la clase OraciónPersonalizada con un delimitador pedido por teclado. Capture la excepción si ésta se produce, presente un mensaje indicando que el delimitador no es válido y cree entonces un objeto OraciónPersonalizada con delimitador ‘,’. 3 de 9 PARTE SEGUNDA: G. Listas 9) Se trata de hacer una clase OraciónListaPalabras que implemente la interfaz Tokenizer del ejercicio 3. Esta clase deberá tener la misma funcionalidad que la clase Oración, sólo que las palabras son almacenadas internamente en una lista de objetos String, en lugar de estar todas en un solo String. Esta clase OraciónListaPalabras tendrá un constructor que recibe un String igual que la clase Oración. Escriba la clase en Java. Puede consultar todos los métodos públicos en la interfaz List de java.util. Pistas (Sólo leer en caso de necesidad y parar de leer si se puede seguir sin ellas).1. Los atributos ahora serán: * List palabras y * int npalab. 2. En lugar de tener los métodos privados contarPalabras y posicionPalabra, se tendrá uno sólo que se podría llamar: - void extraerPalabras(String), el cual será invocado una sola vez desde el constructor y se encargará de añadir las palabras contenidas en el String al atributo de tipo lista. Además contará el número de palabras e inicializará el atributo conveniente. 3. Las operaciones que hay que codificar en este ejercicio son: OraciónListaPalabras(String), void extraerPalabras (String), String obtener (int i), void insertar (String x, int i), String borrar (int i), int numPalabras (). 4. Salvo en extraerPalabras, no se necesitará usar el método “char charAt (int i)” de la clase String. H. Collections 10) Modifique el constructor y el método insertar de la clase OraciónListaPalabras para que después de añadir la/s palabra/s, ordene el atributo lista de palabras por orden alfabético ascendentemente. 11) Supuesta hecha la modificación del ejercicio anterior, añada un método a la clase OraciónListaPalabras llamado ‘encuentra’ que dado un String devuelva un valor lógico indicando si la palabra recibida como parámetro se encuentra en la oración. Intente hacer uso de algún método de utilidad que ya exista. I. Iteradores 12) Añada un método toString a la clase OraciónListaPalabras que represente una oración con una cadena de caracteres de la forma: {hola mi nombre es pedro}. Suponga que no se hizo la modificación del ejercicio 10, sino, las palabras no saldrían con significado de oración. 13) Añada un método marcaPalabrasLargas a la clase OraciónListaPalabras que sustituya en la oración todas las palabras de más de 8 letras por la palabra “(larga)”. Es decir, si la oración es “No tengo más que emancillar el terreno y atisbar el horizonte”, después de llamar a marcaPalabrasLargas, se quedaría en: “No tengo más que (larga) el terreno y atisbar el (larga)” J. Comparadores 14) Añada un método a la clase Oración para comparar una oración con otra. Una oración es menor que otra por el orden alfabético. Recuerde cómo debe llamarse este método, qué recibe y qué devuelve. Recuerde si hay que hacerle algún cambio a la clase Oración al añadir dicho método. Sólo si no lo recuerda, lea las siguientes pistas: ⋅ ⋅ El método que se incluye en la clase para la que se quiera tener un método de comparación es int compareTo (Object). Se declarará a la clase que lo contenga como que implementa la interfaz Comparable. 4 de 9 15) Codifique un método main que se cree un vector de objetos de la clase Oración con los siguientes nombres: “Paula”, “Juan”, “Ana” y “Gabriel”. Acto seguido, ordene dicho vector usando para ello el comparador diseñado en el ejercicio anterior. Intente no leer las pistas. ⋅ ⋅ El método compareTo de Oración es invocado por defecto cuando se necesite comparar objetos Oración. Busque un método para ordenar que ya exista, tenga en cuenta que se pretende ordenar un Array. 16) Construya una nueva forma de comparar objetos Oración, en esta ocasión por el número de palabras en la oración. Tenga en cuenta que se debe mantener como está el método comparador del ejercicio 14. No lea las pistas. ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ Deberá crear una clase comparadora aparte de la clase Oración. Dicha clase se puede llamar ComparaOracionesPorNumeroDePalabras. Esta clase debe implementar la interfaz Comparator. Incluiremos un solo método en ella. El método es int compare (Object, Object). Tenga en cuenta que en este método estamos fuera de la clase Oración. Sólo se podrán usar métodos públicos de Oración en dicho método. 17) Repita el ejercicio 15 pero usando como método de comparación el realizado en el ejercicio anterior. Busque algún método ya implementado. 18) Repita los ejercicios 14 a 17 considerando esta vez la clase OraciónListaPalabras en lugar de la clase Oración. 5 de 9 SOLUCIONES PARTE PRIMERA: A. Lenguaje Java y Arrays 1) Solución.public class PruebaMain { public static void main (String [] args) { float [] v = new float[30]; float media; int n; . . . media = procesaVector(v, n); } public static float procesaVector (float [] w, int n) { float res = 0; if (n > 0) { System.out.print(“[“); for (int i=0; i<n-1; i++) { // Llega hasta el penúltimo System.out.print(w[i] + “, “); res += w[i]; } System.out.print(w[n-1] + “]“); res += w[n-1]; res /= n; } return res; } } B. Orientación a objetos y String 2) Solución.public class Oración { protected String texto; protected int npalab; public Oración (String txt) { texto = txt; contarPalabras(); } protected void contarPalabras () { int i, n = texto.length(); npalab = 0; for (i=0; i<n; i++) { if (texto.charAt(i) == ‘ ‘) 6 de 9 npalab++; } } protected int [] posicionPalabra (int i) { int [] res = new int[2]; int j, k, n = texto.length(); if (i >= 1 && i <= npalab) { k = 1; // Cuenta las palabras que se van recorriendo j = 0; // Es el índice para acceder a los caracteres while (k < i) { if (texto.charAt(j) == ‘ ‘) k++; j++; } res[0] = j; while (texto.charAt(j) != ‘ ‘) j++; res[1] = j-1; } else res[0] = -1; return res; } public String obtener (int i) { if (i >= 1 && i <= npalab) { int [] pos = posicionPalabra(i); return texto.substring(pos[0], pos[1]); } else return “”; } public void insertar (String x, int i) { if (i > 1 && i < npalab) { int [] pos = posicionPalabra(i); texto = texto.substring(0, pos[0] - 1) + x + texto.substring(pos[0], texto.length() – 1); } else if (i == 1) texto = x + “ “ + texto; else if (i == npalab) texto = texto + “ “ + x; } public String borrar (int i) { int [] pos = posicionPalabra(i); String res = “”; if (pos[0] res = int n if (i != -1) { texto.substring(pos[0], pos[1]); = texto.length(); == 1) texto = texto.substring(pos[1]+1, n-1); else if (i == npalab) texto = texto.substring(0, pos[0]-1); 7 de 9 else texto = texto.substring(0, pos[0]-1) + texto.substring(pos[1]+1, n-1); } return res; } public int numPalabras () { return npalab; } } C. Interfaces 3) Solución.public interface Tokenizer { public String obtener (int i); public void insertar (String x, int i); public String borrar (int i); public int numPalabras (); } public class Oracion implements Tokenizer D. Herencia 4) Solución.public class OracionPersonalizada extends Oracion { protected char delimitador; public OracionPersonalizada (String txt, char delim) { texto = txt; delimitador = delim; contarPalabras(); } protected void contarPalabras () { int i, n = texto.length(); npalab = 0; for (i=0; i<n; i++) { if (texto.charAt(i) == delimitador) npalab++; } if (n > 0) npalab++; // No hay un espacio tras la última palabra } protected int [] posicionPalabra (int i) { int [] res = new int[2]; int j, k, n = texto.length(); if (i >= 1 && i <= npalab) { 8 de 9 k = 1; // Cuenta las palabras que se van recorriendo j = 0; // Es el índice para acceder a los caracteres while (k < i) { if (texto.charAt(j) == delimitador) k++; j++; } res[0] = j; while (j < n && texto.charAt(j) != delimitador) j++; res[1] = j-1; } else res[0] = -1; return res; } } E. Clone 5) Solución: En Oracion.public Object clone () throws CloneNotSupportedException { Oracion clon = (Oracion)super.clone(); clon.texto = new String(texto); return clon; } En OracionPersonalizada.public Object clone () { return super.clone(); } F. Excepciones 6) Solución: public String obtener (int i) throws PalabraNoEncontradaException { if (i >= 1 && i <= npalab) { int [] pos = posicionPalabra(i); return texto.substring(pos[0], pos[1]+1); } else throw new PalabraNoEncontradaException(); } public class PalabraNoEncontradaException extends Exception { } public interface Tokenizer { public String obtener (int i) throws PalabraNoEncontradaException; public void insertar (String x, int i); public String borrar (int i); public int numPalabras (); } 9 de 9