miércoles, 29 de abril de 2009

La Clase Scanner de java 5.

La clase Scanner que se introdujo a partir de java 5 tiene varias utilidades. Puede separar o romper su dato de entrada en subcadenas o “tokens” y además convertir estos datos en tipos primitivos como enteros, flotantes, etc. Por ejemplo, puedo pasarle un dato String como argumento al constructor, definir su patrón delimitador (por defecto: espacio en blanco) y obtener subcadenas cuyos miembros debo recoger uno a uno mediante el método next() o algunos de sus similares (nextInt(), nextByte()… para cada dato primitivo existe un next()), veamos un pequeño programa:

public static void main(String[] args) {
    String cadena = "Blog_Acerca_de_Java";
    Scanner s = new Scanner(cadena);
    s.useDelimiter("_");
    while(s.hasNext()){
        System.out.println(s.next()); //s.next() devuelve cadena token
    }
}

En este programa se separarán en subcadenas separando por “_” y se muestra cada término en una línea en la consola de java. Este tipo de uso es muy similar a usar la clase StringTokenizer.
Por otro lado, la clase Scanner también tiene un constructor que recibe un InputStream, por lo que podemos pasarle al mismo la sentencia System.in para leer datos desde el teclado:

public static void main(String[] args) {
    System.out.print("Introduzca datos: ");
    Scanner s = new Scanner(System.in);
    System.out.println(s.next());
    System.out.println(s.nextInt());
    System.out.println(s.nextLine());
}

Este último código lee datos a partir del teclado, separa en subcadenas con espacio en blanco como delimitador, lee la primera cadena y la imprime en consola, espera un espacio, después busca el siguiente dato e intenta convertirlo a entero (int) si no puede hacerlo lanza un InputMismatchException y se detiene, de no lanzar la excepción lee el siguiente dato hasta el final de la línea y lo imprime.
Otro constructor que también nos beneficia es el que recibe un archivo como parámetro. Supongamos que tenemos un archivo con esta información:

Kelvin
30
78,7
Horario: 8am a 4pm

Los datos de este archivo pueden ser tratados mediante el siguiente programa:

public static void main(String[] args) {
    try {
        Scanner s = new Scanner(new File("archivo.txt"));
        System.out.println(s.nextLine());
        System.out.println(s.nextInt());
        s.nextLine();
        System.out.println(s.nextDouble());
        s.nextLine();
        System.out.println(s.nextLine());
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (InputMismatchException e){
        e.printStackTrace();
    }
}

Recuerde colocar el archivo en la misma ruta el paquete del programa. Que fácil en comparación a los códigos de la versión anterior, ahora con la clase Scanner el manejo de archivos de acceso secuencial es mucho más fácil. Bueno, por ahora no tengo más que decir, espero esta información sea de utilidad, hasta una próxima edición.

Más información: Clase Scanner API Java

sábado, 18 de abril de 2009

Argumentos variables y System.out.printf() en Java 5.0 :

Java 5.0 introdujo la lista de argumentos variables mediante la elipsis, esto consiste en colocar tres puntos suspensivos después del tipo de dato en la declaración del método, en el último término (parámetro formal) del mismo de la siguiente manera:

public class ArgumentosVariables {

public ArgumentosVariables(){

System.out.println(sumar(2,3,4,5));

System.out.println(sumar(3,4));

}

public int sumar(int... valor){//Aquí está la elipsis

int resultado=0;

for(int i=0;i<valor.length;i++){

resultado+=valor[i];

}

return resultado;

}

public static void main(String[] args) {

ArgumentosVariables arg=new ArgumentosVariables();

}

}

La cantidad que puede recibir el método sumar puede estar entre cero a cualquiera, por lo tanto además de poder llamar al método sumar enviando dos enteros sumar(1,2) o 6 enteros sumar(1,2,3,4,5,6) también se podría llamar por sumar();y el método devolverá el resultado de la suma como resultado, ya que hace un recorrido por los valores de los argumentos (valor.length ) y suma cada término resultado+=valor[i].

Como se ha dicho, la elipsis sólo se acepta para el último término de la declaración del método, si se cambia la declaración del método sumar por el siguiente:

public int sumar(int... valor, String cadena){

Se arrojará el siguiente error de compilación:

“The variable argument type int of the method sumar must be the last parameter”.

Por lo tanto si puedo hacer:

public int sumar(String cadena, int... valor){

Bueno, en este tema no tengo más que explicar a menos que hayan dudas que quieran resolver por lo cual la parte de comentarios está abierta, por lo tanto he decidido hablar en este mismo artículo acerca del System.out.printf(); que utiliza las facilidades de los argumentos variables para imitar la capacidad de generar una salida por consola a la manera de lenguaje C, echemos un vistazo a la declaración del método printf:

printf (String format, Object... args)

Para los que no están familiarizados con el método, la cadena format indica la cadena que da formato de la salida y los objetos args son los valores que serán sustituidos en la cadena, veamos un ejemplo:

int suma=0, num1=7, num2=3;

suma=num1+num2;

System.out.printf("Al sumar %d mas %d, resulta: %d", num1, num2, suma);

//Salida generada: “Al sumar 7 mas 3, resulta: 10”;

En este caso el primer %d (%d significa numero entero) se sustituye con el primer valor ingresado después de la cadena (num1), luego, el segundo %d se sustituirá por el segundo entero y así sucesivamente, sino es así y por ejemplo se le pasa un valor double el programa compilará pero al ejecutarlo lanzará una java.util.IllegalFormatConversionException.

Si el número de variables de la cadena (tres ‘%d’ en el ejemplo) es menor al número de valores pasados como argumentos el programa compilará e ignorará los valores que están de más, pero si es mayor el programa compila pero arroja un java.util.MissingFormatArgumentException, ya que el número de valores pasados en los argumentos variables no satisface el número de valores esperados de la cadena.

Además de %d existen otros tipos por supuesto, a continuación tenemos los tipos con un ejemplo para cada uno:

%f: Para valores float o double:

System.out.printf("valor flotante: %f", 5.3f);// Salida “valor flotante: 5,300000”

%x.yf: Para float o double con formato ‘x’ dígitos ‘y’ decimales:

System.out.printf("valor pi: %6.4f", Math.PI);// Salida “valor pi: 3,1416” 6 dígitos, 4 decimales.

%x.ye %n: Para Notación científica: ‘x’ dígitos (incluyendo e+ o e-) ’y’ decimales

System.out.printf ("Notacion cientifica = %7.3e %n", 123456.0);//Salida “Notacion cientifica = 1.235e+05”

%o: Octal

System.out.printf("Octal: %o",25);// Salida “Octal: 31”

%h: Hexadecimal

System.out.printf("Hexadecimal: %h",255);

Espero información los ayude.

Bueno, por ahora es todo, hasta una próxima edición. Dios los bendiga.