Sei sulla pagina 1di 17

Scomposizione di stringhe

88

Scomposizione di stringhe
Spesso comodo o naturale per lutente inserire pi
dati per riga
Esistono i metodi next, nextInt, nextDouble di Scanner

Strategia alternativa: leggere un'intera riga con il


metodo nextLine, di Scanner, poi estrarre le
sottostringhe relative ai singoli dati che la compongono
non si pu usare substring, perch in generale non sono
note lunghezza e posizione di inizio dei singoli dati

Una sottostringa delimitata da caratteri particolari


(definiti delimitatori) si chiama lessema o token
I caratteri delimitatori non possono essere usati nei token

Scanner considera come delimitatori di sottostringhe gli


spazi, i caratteri di tabulazione e i caratteri di a capo
Ma i caratteri delimitatori possono essere ridefiniti...
89

Scomposizione di stringhe
Per scomporre una stringa in token usando Scanner,
innanzitutto bisogna creare un oggetto della classe
fornendo la stringa come parametro al costruttore
Scanner in = new Scanner(System.in);
String line = in.nextLine();
Scanner t = new Scanner(line);

Successive invocazioni del metodo next restituiscono


successive sottostringhe, fin quando linvocazione di
hasNext restituisce true
while (t.hasNext())
{ String token = t.next();
// elabora token
}
90

Esempio: contare token in un testo


import java.util.Scanner;
public class TokenCounter
{
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
int count = 0;
while (in.hasNextLine())
{
String line = in.nextLine();
Scanner t = new Scanner(line);
while (t.hasNext())
{
t.next(); // non devo elaborare
count++;
}
}
System.out.println(count + " token");
}
}

91

Scanner e caratteri delimitatori


L'insieme dei caratteri delimitatori usato normalmente
da Scanner indicato con la sequenza di escape
\p{javaWhitespace}
Questa sequenza di escape indica in generale l'insieme
dei caratteri riconosciuti come "spazio" in Java, inclusi i
caratteri \t, \n, \r, ecc.
Una qualsiasi combinazione di uno o pi di questi
caratteri un delimitatore di Scanner
Scanner in = new Scanner(System.in);
System.out.println(in.delimiter());
// stampa a standard output l'insieme di caratteri
// delimitatori attualmente utilizzati dall'oggetto Scanner

92

Scanner e caratteri delimitatori


L'insieme dei caratteri delimitatori da Scanner pu
essere ridefinito
Utile per leggere da file scritti in formato particolare
Esempio: un file csv (comma separated values)
Nome1,Cognome1,Matricola1
Nome2,Cognome2,Matricola2
...

Il metodo useDelimiter di Scanner consente di


specificare un nuovo carattere delimitatore
FileReader reader = new FileReader(file.csv);
Scanner in = new Scanner(reader);
in.useDelimiter(,);
String nome1 = in.next(); // legge il token Nome1 dal file csv
String cognome1 = in.next(); // legge il token cognome1
System.out.println(in.delimiter());

Attenzione: in questo caso il carattere delimitatore


solo la virgola e nessun altro.

93

Scanner e caratteri delimitatori


Problema: come dire al metodo useDelimiter di usare
un insieme di caratteri e loro combinazioni qualsiasi
Soluzione: bisogna usare espressioni canoniche, che
descrivono schemi (pattern) di caratteri
Tali schemi vengono descritti con una particolare sintassi

Esempio: l'espressione canonica [0-9]+ significa


+
[...]
0-9

una qualsiasi combinazione di uno o pi di


uno qualsiasi dei caratteri ...
che siano cifre comprese tra 0 e 9

Esempio: l'espressione canonica che descrive i


delimitatori di default di Scanner \p{javaWhitespace}+
Ovvero, uno o pi caratteri spazio (\t,\n,\r, ecc.)

Per approfondimenti: consultare la documentazione


della classe Pattern nella libreria standard

94

Riassunto: elaborare input in java


Principali classi e metodi utilizzabili
Scanner e nextLine per leggere intere righe di input
Classe FileReader per gestire input da file

Scanner e next per scomporre le righe in parole


Metodo useDelimiter per ridefinire I caratteri delimitatori di
un oggetto di tipo Scanner

Integer.parseInt() e Double.parseDouble() per convertire


stringhe in numeri

Situazioni da gestire
Terminazione di input: metodo hasNextLine() di
Scanner, e/o uso di caratteri sentinella (ad es. Q)
IOException (gestione obbligatoria) se lavoriamo con file
NumberFormatException (gestione opzionale) lanciate
da Integer.parseInt() e Double.parseDouble()
95

Reindirizzamento
di input e output,
canalizzazioni (pipes)

96

Reindirizzamento di input e output


Usando i programmi scritti finora si inseriscono dei dati
da tastiera, che al termine non vengono memorizzati
Ad esempio, se si elabora una serie di stringhe che
vengono inserite dall'utente, al termine dell'esecuzione
del programma non rimane traccia delle stringhe inserite.

Una soluzione sarebbe che l'input da tastiera da fornire


al programma venisse memorizzato in un file
Questo si pu fare con il reindirizzamento dellinput
standard, consentito da quasi tutti i sistemi operativi
Attenzione: diverso da aprire un file in lettura. In
questo caso il contenuto del file viene letto come se
fosse l'input standard
Attenzione: all'esame faremo cos per collaudare i nostri
programmi
97

Reindirizzamento di input e output


//classe che ripete a pappagallo l'input inserito, 1 token a riga
import java.util.Scanner;
public class Pappagaller
{
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
while(in.hasNext())
System.out.println(in.next());
}
}

Il reindirizzamento dellinput standard, sia in sistemi Unix


che nei sistemi MS Windows, si indica con il carattere <
seguito dal nome del file da cui ricevere linput
java Pappagaller < testo.txt

Il file testo.txt viene collegato allinput standard


Il programma non ha bisogno di alcuna istruzione
particolare, semplicemente System.in non sar pi
collegato alla tastiera ma al file specificato
98

Reindirizzamento di input e output


A volte comodo anche il reindirizzamento delloutput
Ad esempio, quando il programma produce molte righe di
output, che altrimenti scorrono velocemente sullo
schermo senza poter essere lette
java Pappagaller > output.txt

Il file output.txt viene collegato alloutput standard


Il programma non ha bisogno di alcuna istruzione
particolare, semplicemente System.out non sar pi
collegato alla shell ma al file specificato

I due reindirizzamenti possono anche essere


combinati
java Pappagaller < testo.txt > output.txt
99

Canalizzazioni (pipes)
Supponiamo di dovere ulteriormente elaborare l'output
prodotto da un programma
Ad esempio, una elaborazione molto comune consiste
nellordinare le parole
questa elaborazione cosi` comune che molti sistemi
operativi hanno un programma sort, che riceve da
standard input un insieme di stringhe (una per riga) e le
stampa a standard output ordinate lessicograficamente
(una per riga)
Per ottenere le parole di testo.txt una per riga e ordinate,
abbiamo bisogno di un file temporaneo (ad es. temp.txt)
che serve solo a memorizzare il risultato intermedio,
prodotto dal primo programma e utilizzato dal secondo
java Pappagaller < testo.txt > temp.txt
sort < temp.txt > testoOrdinato.txt

100

Canalizzazioni (pipes)
Anzich utilizzare un file temporaneo per memorizzare
loutput prodotto da un programma che deve servire da
input per un altro programma, si pu usare una
canalizzazione (pipe)
java Pappagaller < testo.txt | sort > testoOrdinato.txt

La canalizzazione pu anche prolungarsi


Ad esempio, vogliamo sapere quante parole ci sono nel
testo, senza contare le ripetizioni
Usiamo sort con l'opzione -uf (non ripete parole uguali,
e non considera differenze tra maiuscole e minuscole)
Canalizziamo il risultato sul programma wc (word count)
java Pappagaller < testo.txt | sort | wc
101

Il flusso di errore standard

102

Il flusso di errore standard


Abbiamo visto che un programma Java ha sempre due
flussi ad esso collegati, forniti dal sistema operativo
il flusso di ingresso standard, System.in
il flusso di uscita standard, System.out

In realt esiste un altro flusso


Il flusso di errore standard (standard error), System.err
System.err di tipo PrintStream come System.out

La differenza tra out e err solo convenzionale


si usa System.out per comunicare allutente i risultati
dellelaborazione o qualunque messaggio previsto dal
corretto e normale funzionamento del programma
si usa System.err per comunicare allutente eventuali
condizioni di errore (fatali o non) verificatesi durante il
funzionamento del programma
103

Il flusso di errore standard


In condizioni normali (cio senza redirezione) lo
standard error finisce sullo schermo insieme allo
standard output
System.out.printl(Tutto ok);
System.err.println(Errore!);

In genere il sistema operativo consente di effettuare la


redirezione dello standard error in modo indipendente
dallo standard output
in Windows possibile redirigere i due flussi verso due
file distinti
C:\> java HelloTester > out.txt 2> err.txt

in Unix (solitamente) possibile redirigere i due flussi


verso due file distinti (la sintassi dipende dalla shell)
104

Potrebbero piacerti anche