8.5. Input e Output em Java

System.out é um objeto. Este objeto sabe como escrever informação no standard output (em geral o ecrã). Quando invocamos os métodos print e println, invocamo-los sobre este objeto, ou seja, o System.out é o alvo da invocação destes métodos.

Também existe um objeto chamado System.in que permite ler valores do standard input (em geral o teclado). No entanto, este objeto não torna fácil essa leitura de valores a partir do teclado.

Vamos usar um outro objeto que nos vai facilitar a interpretação da informação obtida pelo System.in: uma instância da classe Scanner (do pacote java.util) .

Este objeto vai-nos ajudar a “trazer para dentro do nosso programa” a informação que o utilizador digita no teclado.

Consulte a documentação da classe Scanner do pacote java.util em https://docs.oracle.com/javase/9/docs/api/java/util/Scanner.html.

8.5.1. Input do teclado – usando Scanner

Um objeto Scanner é um objeto que

 

O objeto System.in representa um canal de leitura (em geral o teclado).

Como tal, podemos usá-lo como origem da informação, para que algum objeto Scanner possa “consumir” os tokens que o utilizador escreve.

Fazemos isso quando criamos o objeto do tipo Scanner, indicando que o canal de leitura que ele vai usar é o System.in:

Agora já podemos invocar métodos que lêem informação a partir do teclado tendo como alvo da invocação este objeto.

Por exemplo, o método String nextLine() lê todos os carateres até encontrar um caráter especial que representa um “fim de linha” (gerado, por exemplo, quando o utilizador carrega na tecla Enter) e retorna a String contendo esses carateres.

Outros exemplos são o método String next() que lê a próxima token e retorna-a como uma String, e o método int nextInt() que lê a próxima token e retorna-a como um inteiro.

Por defeito, os delimitadores que definem até onde se estende uma token são o espaço, o tab ou o fim de linha.

As instruções seguintes:

produzem o seguinte efeito no ecrã caso o utilizador introduza os valores Pai Natal e 524:

Repare que o input do utilizador, embora escrito no teclado, é reproduzido pelo sistema operativo no ecrã.

Suponha que queremos garantir que o utilizador introduz um valor entre 1 e 20. Se isso for importante, não basta dizer isso ao utilizador. Ele pode, mesmo sem querer, escrever um valor não aceitável.

É muito importante que o programa consiga recusar valores e repetir o pedido enquanto o utilizador não introduz um valor aceitável.

O programa seguinte pede uma nota entre 1 e 20 ao utilizador, só aceitando um valor que satisfaça essa condição.

Exemplo de execução deste programa:

 

Os métodos int nextInt() e double nextDouble(), que lêem a próxima token acessível no canal de leitura sobre o qual o Scanner trabalha, provocam um erro de execução no caso de a token lida não constituir um valor numérico do tipo correspondente.

Os valores que estes métodos conseguem manipular são

Quando a próxima token no canal de leitura não tem estas características (por exemplo, porque contém uma letra ou carácter especial) o erro consequente é representado por uma exceção do tipo InputMismatchException.

Considere o seguinte pedaço de um programa:

No caso em que o utilizador insere, por exemplo, 2 e 1.5, o efeito destas instruções é:

Quando o utilizador insere, por exemplo, 1q3 em vez de um inteiro, o efeito é:

O mesmo aconteceria se o utilizador introduzisse qualquer caráter que não fosse um algarismo ou um ponto, quando lhe fosse pedido um número com parte decimal (através do método nextDouble()).

Se quisermos tornar o nosso programa robusto no sentido de não “rebentar” no caso de o utilizador não introduzir um número inteiro quando o programa quer consumir um número inteiro, podemos testar cada token que é lida do canal de leitura e só o aceitar se for realmente um inteiro.

Para isso usamos o método hasNextInt() que “espreita” para o canal de leitura e retorna true se a próximo token for um número inteiro e false caso contrário.

Conforme o resultado deste método (true ou false), podemos escolher

Exemplo de execução deste programa:

Os seguintes métodos podem ser usados para fazer leitura robusta de inteiros num dado intervalo:

A seguinte instrução poderia então ser escrita num programa que tivesse acesso a estes métodos, para receber do utilizador um valor inteiro entre 1 e 20:

 

 


 

Anterior: 8.4. A classe StringBuilder

Seguinte: 8.6. Aliasing