REPUBLICA BOLIVARIANA DE VENEZUELA. UNIVERSIDAD DEL ZULIA FACULTAD DE INGENIERÍA DIVISIÓN DE POSTGRADO COMPUTACIÓN APLICADA TÉCNICAS DE PROGRAMACIÓN: TAREA 4 (JAVA) Profesor: Ing. Daniel Finol Nombre: José V. Gómez D. CI: 10.084.584. MARACAIBO, JUNIO DEL 2006. I. Tarea 3: Traducir el programa de la tarea 3 a Java: 1. Deben crear una clase "Pila" aparte del programa principal (para ser usado por éste). 2. Dicha clase debe estar en un paquete con el nombre de su preferencia. Consideraciones: Se evaluará, además de lo usual, el buen diseño de los objetos (por ejemplo: asegúrense de hacer privados los miembros que deban serlo). Ya que Java libera la memoria de manera automática (aunque retardada) con su "recolector de basura" (garbage collector), no necesitan liberar memoria Uds. mismos. Sugerencias: Para trabajar con su propio paquete deben hacer lo siguiente: o La primera línea del archivo de la clase que quieren que esté dentro de un paquete debe ser: package miPaquete; o En el programa donde usen la clase de dicho paquete deben tener la línea: import miPaquete.NombreDeLaClase; o bien import miPaquete.*; o Al compilar la clase que va a estar dentro del paquete pueden usar la siguiente opción: javac -d . miClase.java (-d le indica al compilador dónde colocar lo archivos .class generados y el punto le indica que use el directorio actual; esto es necesario para que cree los subdirectorios según el nombre del paquete). o Para correr el programa que use alguna clase del paquete lo más fácil es que lo ejecuten a partir del directorio desde el cuál se creó el subdirectorio del paquete; sino pueden usar la opción -classpath o modificar la variable de entorno CLASSPATH. Para trabajar con archivos pueden usar el siguiente código: o import java.io.*; o El main debe tener la siguiente forma (o cualquier función donde usen archivos): public static void main(String args[]) throws IOException { (la razón se explicará luego). o En nuestro caso podemos usar lo siguiente para abrir los archivos: BufferedReader archi; BufferedWriter archo; if(args.length >= 1) archi = new BufferedReader(new FileReader(args[0])); else archi = new BufferedReader(new InputStreamReader(System.in)); if(args.length >= 2) archo = new BufferedWriter(new FileWriter(args[1])); else archo = new BufferedWriter(new OutputStreamWriter(System.out)); o Para leer un caracter pueden usar la función read() de BufferedReader. (Devuelve -1 en fin de archivo). o Para escribir un caracter usen la función write(c) de BufferedWriter. (Deben seguirla de una llamada a la función flush() de la misma clase). Como las variables tipo objeto son referencias (especie de apuntadores implícitos) una clase puede tener un campo de su mismo tipo (una referencia a sí misma): class Abc {int i; Abc ziggy; }. Además a toda variable tipo objeto se le puede asignar el valor null. En http://java.sun.com/j2se/1.5.0/docs/api/ pueden consultar la referencia de la "biblioteca estándar" (API) de Java. En el paquete java.io está lo referente a archivos. Recuerden que no se evalúa sólo que el programa funcione sino su lógica, su legibilidad y su portabilidad. Explicación del Código fuente en java: En la función main se introducen los argumentos (archivo de entrada, archivo de salida) para leer del archivo de entrada carácter por carácter su contenido ( si no existe lo lee de la entrada estándar) y la salida la coloca en el archivo de salida ( si no existe lo escribe en la salida estándar). Para trabajar con archivos se usamos: import java.io.*; // se coloca en las primeras lineas public static void main(String[] args)throws IOException { BufferedReader entra; BufferedWriter sale; if(args.length >= 1) entra = new BufferedReader(new FileReader(args[0])); else entra = new BufferedReader(new InputStreamReader(System.in)); if(args.length >= 2) sale = new BufferedWriter(new FileWriter(args[1])); else sale = new BufferedWriter(new OutputStreamWriter(System.out)); Si no se puede abrir el archivo de entrada se envía un error a la salida estándar: if (entra== null) System.out.println("\nError: entrada:"+args[0]); No se pudo abrir archivo de Dentro de la función principal -main( )- tenemos: * Si se cumple args.length >=1 : Se lee de un archivo de entrada de extensión .txt , sino de la entrada estándar sino . Si se cumple args.length >= 2 : Se imprime en un archivo de salida de extensión .txt , sino en la salida estándar sino Se usa una pila dinámica la cual utilizamos para llevar el control de abrir y cerrar llaves -“(“, “[“, “{“ , “}”, “]”, “)” – que están fuera de las comillas . Esta pila se va llenando al obtener el carácter lee ido de la entrada estándar y llamar función push, luego al leer un carácter de las llaves nombradas se vacía la pila al llamar la función pop (si se encuentra con un tipo de llave es cuando se introduce o se saca de la pila). Esto se va canalizando a través de un switch-case. Esta pila dinámica esta dentro de un package (es una carpeta). Por lo que la primera línea de la pila es package pila; La pila se realizo en la clase llamada pila que utilaza otra clase llamada Nodo. En la pila se encuentra los métodos push y pop, para introducir o sacar caracteres en la misma. Para usar la clase pila de del paquete pila se coloca en las primeras líneas: import pila.*; Además se coloca: pila p = new pila();//Pila externa pila pi = new pila();//Pila interna El ciclo while ayuda a verificar e imprimir carácter por carácter del texto hasta que se consigue un error (llaves no cerradas correctamente) . Se verifica si se abrió una comilla para no tomarlas en cuenta en la validación de cierre de los caracteres “(“, “[“, “{“ , “}”, “]”, “)” externos con : if (comi==2) comi=0; if (c=='"' || comi==1 ){ /*se cumple al estar abierto una comilla*/ if (c=='"'=='"' && comi==1) comi=2; . . . if (c=='"'&& comi==0) comi=1; Sino se cumple - if (c=='"'=='"' && comi==0) – se lleva el control de las llaves externas. Sino no se abrió una comillas o se cerro una comilla abierta se hace la validación de paréntesis, corchetes y llaves - “(“, “[“,y“{“ - abiertas para ver si están cerradas correctamente . Esto se hace al conseguir un paréntesis, corchete y llave abierta y sacando del tope de la pila (con la función pop) el paréntesis, corchete o llave para compararlos y verificar así que este cerrado correctamente. Si no esta cerrado correctamente se dice cual es el error y en que línea y columna esta el mismo (esto se muestra a la salida estándar. Este conteo, de las líneas y columnas, se hace a través de: if (c!='\n'){ i++; if (i==1){ if (args.length>=2){ sale.write("\n"+(linea+1)+":"+"\t\t");sale.flush(); } else System.out.print("\n"+(linea+1)+":"+"\t\t"); } if (args.length>=2){ sale.write(c);sale.flush();/*Imprime caracter leido en archivo de salida*/ } else System.out.print(c);//Imprime caracter leido en salida estandar } else{ i=0; linea++; } // Cierre del if (c!='\n') Al cumplirse - if (c=='"'' & comi==0) – se lleva el control de las llaves internas y se termina de examinar al conseguir el error. Para llevar el control de las llaves internas (dentro de las comillas) se hace lo mismo que se hizo para las llaves externas. Usando otra pila dinámica. Todo esto se hace dentro ciclo while ( las dos pilas se llena y vacían aquí para llevar el control interno y externo de las llaves) . CODIGO FUENTE DEL PROGRAMA: TAREA4.java CODIGO FUENTE DEL PACKAGE PILA: pila.java y nodo.java CODIGO FUENTE DEL PROGRAMA: