# Appendice A: utilizzo classe Scanner

La classe `java.util.Scanner`  è una classe di utilità per leggere da vari input e ha metodi comodi per lavorare con l'input. Scanner è una classe wrapper di sorgenti di input. Le sorgenti i input possono essere un oggetto di tipo `Reader`, un `InputStream`, una `String` o un `File`.

Si può usare `Scanner` per leggere da standard input:

```java
Scanner standardInputScanner = new Scanner(System.in);
```

e se *charSource* è di tipo `Reader`, si può creare uno `Scanner` per leggere da *charSource*, così:

```java
Scanner scanner = new Scanner(charSource);
```

Quando processa un input Scanner lavora con **tokens**. Un token è una stringa di caratteri che non può essere ulteriormente separata. Un token può essere una singola parola o una stringa di caratteri che rappresenta un valore di tipo **double**. Nel caso di uno scanner, i tokens sono separati da "delimitatori". I delimitatori sono caratteri di spazio, tabs e caratteri di fine linea. Normalmente i caratteri spazio sono utilizzati per separare le parole e sono scartati dallo scanner. Lo scanner a metodi d'istanza per leggere tokens di vario tipo.&#x20;

Supponendo che la variabile *stdin* sia di tipo `Scanner`, abbiamo la funzione `stdin.netxInt()` che legge un valore di tipo **int** dall'utente e lo ritorna. Ci sono metodi corrispondenti per leggere altri tipi, inclusi `stdin.nextDouble()`, `stdin.nextLong()` e `stdin.nextBoolean()` (accetta sono "*true*" o "*false*" come input). Il metodo `stdin.nextLine()` legge una riga di input e `stdin.next()` ritorna una stringa di non spazi vuoti.

Esempio di programma che legge da console, i parametri di input, valori double di quantità investita, tasso di interesse e calcola in un anno, il valore dell'interesse e il nuovo capitale:

```java
import java.util.Scanner;

public class Interest2WithScanner {
	public static void main(String[] args) {
		Scanner stdin = new Scanner(System.in); // Create the Scanner.
		double principal; // The value of the investment.
		double rate; // The annual interest rate.
		double interest; // The interest earned during the year.
		System.out.print("Enter the initial investment: ");
		principal = stdin.nextDouble();
		System.out.print("Enter the annual interest rate (as a decimal): ");
		rate = stdin.nextDouble();
		interest = principal * rate; // Compute this year’s interest.
		principal = principal + interest; // Add it to principal.
		System.out.printf("The amount of interest is $%1.2f%n", interest);
		System.out.printf("The value after one year is $%1.2f%n", principal);
	} // end of main()
} // end of class Interest2WithScanner
```

Se il valore immesso dall'utente con è compatibile con quello dalla funzione di `Scanner`, viene lanciata un'eccezione di tipo runtime, `java.util.InputMismatchException`.

Ad esempio, se digito "*ciao*" quando mi chiede la quantità da investire, viene sollevata l'eccezione:

```
Enter the initial investment: ciao
Exception in thread "main" java.util.InputMismatchException
	at java.util.Scanner.throwFor(Scanner.java:864)
	at java.util.Scanner.next(Scanner.java:1485)
	at java.util.Scanner.nextDouble(Scanner.java:2413)
	at Interest2WithScanner.main(Interest2WithScanner.java:10)
```

Ricapitolando, ammettiamo di avere una variabile *scanner* di tipo `Scanner`. Allora noi abbiamo:

* `scanner.next()` - legge il prossimo token dalla sorgente di input e ritorna come `String`;
* `scanner.nextInt()`, `scanner.nextDouble()`, e così via - legge il prossimo token dalla sorgente di input e cerca di convertirlo in tipo *int*, *double* e così via. Ci sono metodi per leggere valori di ogni tipo primitivo;
* `scanner.nextLine()` - legge una riga intera, fino alla prossima riga, e ritorna la riga come *String*. Il carattere di fine linea è letto ma non fa parte della stringa ritornata. Nota che questo metodo **non** è basato sui token. Un'intera riga è letta e ritornata inclusi i caratteri di spazio presenti nella riga. Il valore di ritorno può anche essere una stringa vuota.

Tutti questi metodi possono generate delle eccezioni. Se un tentativo è fatto per leggere oltre la fine dell'input, è lanciata un'eccezione `java.util.NoSuchElementException`. Metodi come `scanner.nextInt()` lanciano un'eccezione di tipo `java.util.InputMistmatchException` se il token successivo nell'input non rappresenta un valore del tipo richiesto.  Le eccezioni che possono essere generate non richiedono una gestione delle eccezioni obbligatoria, in quanto eccezioni di tipo runtime.

La classe `Scanner`, ha anche dei metodi per testare il tipo di input successivo. Possiamo interrogare lo scanner per sapere se ci sono altri token dopo o se il token successivo è del tipo desiderato:

* `scanner.hasNext()` - ritorna un valore **boolean** *true*, se c'è almeno un atro token nello stream di input;
* `scanner.hasNextInt()`, `scanner.hasNextDouble()`, .... - ritorna un valore **boolean** *true* se c'è almeno un altro token nello stream di input e se il token rappresenta un valore nel tipo cercato;
* `scanner.hasNextLine()` - ritorna un valore **boolean** *true* se almeno un'altra riga nello stream di input;
