Cursos gratuitos de programacion de ordenadores, en español

AnteriorPosterior

8a. Cómo leer datos desde consola.

  Curso: Introducción a Java

8. Datos introducidos por el usuario

8.1. Cómo leer datos desde consola

Como ya hemos comentado en más de una ocasión, leer desde teclado usando Java no es trivial:

  • Habrá que interceptar los posibles errores (por ejemplo, que ni siquiera exista un teclado). Por eso, toda la construcción de lectura de teclado deberá ir encerrada en un bloque "try...catch" ("intentar hacer... interceptar posibles errores"; veremos esta construcción más adelante con mayor detalle).
  • Deberemos usar la entrada del sistema ("System.in"), pero enmascarándola dentro de un flujo de datos de entrada ("InputStreamReader"), al que deberemos acceder mediante un buffer intermedio ("BufferedReader").
  • Por esta estructura, deberemos indicar que queremos usar ciertas funciones de entrada y salida ("import java.io.*;").

Con todas esas consideraciones, un programa básico que pidiera su nombre al usuario y le saludara mediante ese nombre podría ser así:

//  
// Ejemplo 1 de como pedir datos al usuario  
//  
 
import java.io.*;
 
class Hola { 
  public static void main( String args[] ) { 
    String nombre = "";
 
    System.out.print( "Introduzca su nombre: " ); 
    try { 
      BufferedReader entrada = 
        new BufferedReader(new InputStreamReader(System.in));   
      nombre = entrada.readLine(); 
    }
    catch (IOException e) {}
    System.out.println( "Hola, " + nombre );
  } 
} 
 

Es complejo como para hacerlo "de memoria". Más adelante profundizaremos más, pero por ahora nos limitaremos a "copiar y pegar" esa estructura para poder hacer programas básicos "en modo texto" que pidan datos al usuario.

Ejercicio propuesto 8.1.1: Crea un programa que te pida tu nombre y escriba un triángulo con las letras que lo forman, mostrando primero la primera letra, luego las dos primeras y así sucesivamente, hasta llegar al nombre completo, como en este ejemplo:
N
Na
Nac
Nach
Nacho
(Pista: tendrás que usar "substring" y un bucle "for")

Ejercicio propuesto 8.1.2: Crea un programa que te pida tu nombre y escriba la primera letra en mayúsculas y el resto en minúsculas.

Ejercicio propuesto 8.1.3: Crea un programa que te pida tu nombre y escriba las letras separadas por espacios. Por ejemplo, a partir de "Nacho" escribirá "N a c h o".

8.2. Pedir datos numéricos.

También es habitual manejar datos numéricos. Como el resultado de "readLine" es un cadena de texto, tendremos que calcular su valor numérico. Para un número entero, esto se hace con "Integer.parseInt":

//  
// Ejemplo 2 de como pedir datos al usuario  
//  
 
import java.io.*;
 
class Doble { 
  public static void main( String args[] ) { 
    int numero = 0;
 
    System.out.print( "Introduzca un numero: " ); 
    try { 
      BufferedReader entrada = 
        new BufferedReader(new InputStreamReader(System.in));   
      numero = Integer.parseInt( entrada.readLine() ); 
    }
    catch (IOException e) {}
    System.out.println( "Su doble es: " + numero*2 );
  } 
} 
 

Los valores que demos dentro de un bloque try...catch no se pueden usar desde fuera de ese bloque. Por eso hemos estado dando valores iniciales a las variables, o el programa no compilaría. Otra alternativa poco elegante, pero sencilla y aceptable en un programa tan simple creado por un principiante sería que todo el fragmento de programa que manipule esas variables esté dentro del try...catch. Así, podríamos sumar dos números haciendo:

//  
// Ejemplo 3 de como pedir datos al usuario  
//  
 
import java.io.*;
 
class Sumar { 
  public static void main( String args[] ) { 
    try { 
      BufferedReader entrada = 
        new BufferedReader(new InputStreamReader(System.in));   
 
      System.out.print( "Introduzca un numero: " );
      int numero1 = Integer.parseInt( entrada.readLine() ); 
 
      System.out.print( "Introduzca otro numero: " );
      int numero2 = Integer.parseInt( entrada.readLine() ); 
 
      System.out.println( "Su suma es: " + numero1+numero2 );
    }
    catch (IOException e) {}
  } 
} 
 

Ejercicio propuesto 8.2.1: Crea un programa que te pida dos números (enteros) y muestre su división (entera) y el resto de dicha división. Por ejemplo, si los números son 16 y 3, la división sería 5 y el resto sería 1.

Ejercicio propuesto 8.2.2: Crea un programa que te pida dos números enteros y diga si el primero es múltiplo del segundo.

8.3. Otra forma aparentemente más sencilla

Si nos molesta tener que usar el bloque try...catch, hay una forma más compacta de escribir casi lo mismo, añadiendo "throws" a la declaración de la función, para indicar que puede lanzar una excepción:

//  
// Otra forma de pedir datos al usuario  
//  
 
import java.io.*;
 
class Hola2 { 
  public static void main( String args[] ) throws IOException { 
    String nombre;
 
    System.out.print( "Introduzca su nombre: " ); 
 
    BufferedReader entrada = 
      new BufferedReader(new InputStreamReader(System.in));   
    nombre = entrada.readLine(); 
 
    System.out.println( "Hola, " + nombre );
  } 
} 
 

Pero cuidado: NO es exactamente lo mismo. Esta construcción avisa al programa "superior" de que esa función puede lanzar una excepción, de modo que estamos aplazando la comprobación de errores con try...catch, para que no la haga nuestra función, sino el programa que la llama. En nuestro caso, como nuestra función es el cuerpo del programa ("main"), estamos pasando la pelota a... ¡nadie!... así que estamos despreciando por completo la comprobación de errores, que puede no ser una solución aceptable en problemas "reales".

Ejercicio propuesto 8.3.1: Crea un programa que te pida tu nombre y escriba las letras separadas por espacios, usando "throws" en vez de "try-catch". Por ejemplo, a partir de "Nacho" escribirá "N a c h o".

8.4. Usando la clase "Scanner"

A partir de la versión 5 de Java, tenemos otra posibilidad que simplifica ligeramente el acceso a teclado: la clase Scanner. En su uso más sencillo, le indicamos qué flujo de datos debe analizar (ya sea un fichero o la entrada estándar del sistema, "Sytem.in"), y vamos obteniendo el siguiente dato con ".next" (el siguiente hasta llegar a un espacio en blanco):

//  
// Pedir datos al usuario de forma mas simple,
// palabra por palabra (Java 5 o superior)
//  
 
import java.io.*;
import java.util.Scanner;
 
class Scanner1 { 
  public static void main( String args[] ) throws IOException { 
    String nombre;
 
    System.out.print( "Introduzca su nombre (una palabra): " );   
 
    Scanner entrada=new Scanner(System.in);
    nombre = entrada.next();
 
    System.out.println( "Hola, " + nombre );
  } 
} 
 

No sólo podemos leer cadenas de texto. Si lo siguiente que queremos leer es un número, podemos usar ".nextInt", ".nextFloat", ".nextDouble"... Y si queremos obtener más de un dato, podemos repetir con ".hasNext" ("tiene siguiente"), que nos devolverá verdadero o falso. Típicamente se usaría como parte de un bucle "while".

while (entrada.hasNext()) { 

Finalmente, si queremos usar la clase "Scanner" para que lea línea a línea, en vez de interrumpirse cada vez que encuentre un espacio en blanco, podemos cambiar el "delimitador" con ".useDelimiter". Por ejemplo, para que se interrumpa cuando llegue a un final de línea, indicaríamos como delimitador el que esté definido en la propiedad "line.separator" (separador de línea) del sistema, así:

//  
// Pedir datos al usuario de forma mas simple,
// permitiendo espacios (Java 5 o superior)
//  
 
import java.io.*;
import java.util.Scanner;
 
class Scanner2 { 
  public static void main( String args[] ) throws IOException { 
    String nombre;
 
    System.out.print( "Introduzca su nombre (una o varias palabras): " );   
 
    Scanner entrada=new Scanner(System.in);
    entrada.useDelimiter(System.getProperty("line.separator")); 
    nombre = entrada.next();
 
    System.out.println( "Hola, " + nombre );
  } 
} 
 

Ejercicio propuesto 8.4.1: Crea un programa que te pida tu nombre y escriba las letras separadas por espacios, usando "Scanner".

Actualizado el: 05-07-2013 15:13

AnteriorPosterior