I seguenti package contengono funzioni e metodi per gestire l'input:
- package fmt
- package bufio
- package strings
- package ioutil
## L'input può provenire da
- standard input (tastiera o file ridiretto)
```
$ ./myProgram1
sto inviando dati da tastiera
$ ./myProgram1 < myInputFile
```
*Nel secondo caso lancio lo stesso identico programma (myProgram1.go), ma (come utente) uso il file myInputFile invece della tastiera per fornire l'input.*
- linea di comando (salvato automaticamente in `os.Args`)
```
$ ./myProgram2 scrivo qui i dati per il programma
```
*In questo caso, ogni volta che viene eseguito il programma, tutte le parole che seguono il nome del programma vengono salvate automaticamente nella slice os.Args a partire da os.Args[1].*
*Quindi in questo esempio specifico in os.Args[1] viene salvata la stringa "scrivo", in os.Args[2] "qui", in os.Args[3] "i", ..., in os.Args[7] "programma".*
*Nota: in os.Args[0] viene salvato il nome dell'eseguibile (./myProgram2).*
- file
```
$ ./myProgram3 myInputFile
```
*In questo caso il programma myProgram3.go, una volta lanciata l'esecuzione, si troverà (automaticamente) in os.Args[1] il nome del file ("myInputFile"), che potrà aprire (e chiudere) e leggere (vedi più avanti come).*
**Ricordarsi di fare sempre i controlli per evitare panic!**
---
**Nota di terminologia**. Useremo il termine *stringa* per denotare una qualsiasi sequenza di caratteri, che può quindi contenere anche spazi bianchi, tab, ecc., e invece con il termine "parola" una sequenza di caratteri senza spazi bianchi, tipicamente delimitata da essi. Ad esempio:\
"Sempre caro mi fu quest’ermo colle, e questa siepe," è una stringa.\
Per leggere **da standard input un dato o una lista di dati separati da spazi bianchi** (non importa quanti spazi e non importa di che tipo, se ' ', '\n\', '\t', ...), la soluzione più semplice è:\
`fmt.Scan(&var_1, &var_2, ..., &var_n)`
Ad esempio:
```go
var nome, cognome string
var altezza int
var peso float64
fmt.Scan(&nome, &cognome, &altezza, &peso)
```
### bufio.Scanner su os.Stdin
Per leggere **da standard input righe di un testo**, si usa Scanner di bufio. Tipicamente:
```go
myScanner := bufio.NewScanner(os.Stdin)
for myScanner.Scan() {
line := myScanner.Text()
....
}
```
Se la riga è una sola:
```go
myScanner := bufio.NewScanner(os.Stdin)
myScanner.Scan() {
line := myScanner.Text()
....
```
---
### bufio.Scanner su file
Per leggere **righe di un testo da file** anche si usa Scanner di bufio, come sopra, con in più l'apertura e la chiusura del file:
```go
varfileNamestring
...
myFile,err:=os.Open(fileName)
iferr!=nil{
fmt.Println("file not found")
return
}
defermyFile.Close()
myScanner:=bufio.NewScanner(myFile)
formyScanner.Scan(){
line:=myScanner.Text()
....
}
```
### bufio.Scanner con "passo" più piccolo
Per leggere **procedendo per byte, rune o parole** invece che per righe, si usa il metodo Split(bufio.ScanXxx), che modifica appunto il modo di procedere di Scan().
Anche procedendo per byte o rune, si ottengono sempre stringhe, in questi casi di 1 solo carattere.
```go
...
myScanner:=bufio.NewScanner(myFile)
myScanner.Split(bufio.ScanWords)//o ScanBytes o ScanRunes
formyScanner.Scan(){
word:=myScanner.Text()//Sto leggendo parola per parola
....
}
```
```go
...
myScanner:=bufio.NewScanner(myFile)
myScanner.Split(bufio.ScanRunes)//Ora voglio leggere runa per runa
formyScanner.Scan(){
oneRuneString:=myScanner.Text().//Anche in questo caso Text() restituisce una stringa, di sola runa
....
}
```
### Funzioni di libreria per spezzare l'input
**In alternativa a Split(bufio.ScanWords)**, il package `strings` mette a disposizione:
```go
strings.Fields(sstring)
```
che restituisce una slice di stringhe che contiene le parole di `s`, cioè le sottostringhe identificate da spazi bianchi.
Ricordatevi sempre anche del vecchio fmt.Scan, che risolve molte situazioni in modo semplice.
---
# Pre-elaborazione / estrazione di dati
### Estrazione di elementi singoli da un contesto, come cifre da un numero o caratteri da una stringa
- cifre da un numero n
- se è stato salvato come int, con un ciclo
```go
forn>0{
cifra:=n%10
n/=10
}
```
- se è stato salvato come stringa, con ciclo
```go
fori:=0;i<len(s);i++{
cifra:=n[i]
}
```
- caratteri da una stringa s
- se byte, con ciclo di conteggio
```go
fori:=0;i<len(s);i++{
cifra:=s[i]
}
```
- se rune, con un for range
```go
for_,cifra:=ranges{
...
}
```
- o con un ciclo di conteggio
```go
slice:=[]rune(s)
fori:=0;i<len(slice);i++{
cifra:=slice[i]
}
```
---
### Estrazione di dati da una stringa formattata
Ad esempio, una data gg/mm/aaaa
Per quando le righe o le stringhe in input che hanno un **formato fissato**,
- se c'è un solo tipo di separatore:
- strings.Split(s, sep string)
- Esempio:
```go
sep:="/"
slice:=strings.Split(s,sep)
```
- se ci sono diversi separatori, il package `fmt` mette a disposizione la funzione `Scanf`, che usa una sintassi analoga a `Printf` per leggere e memorizzare valori (invece di stamparli):
```go
fmt.Scanf(formatstring,listadipuntatoriavar)
```
Ad esempio
```go
varore,min,secint
//stampo orario in formato h:m:s
fmt.Prinf("%d:%d:%d",ore,min,sec)
//leggo orario (da tastiera), con i valori
//di ore, min e sec in una stringa in formato h:m:s
fmt.Scanf("%d:%d:%d",&ore,&min,&sec)
```
E anche Sscanf per estrarre dati da una stringa
- Esempio:
```go
stringData:="15/12/2022"
fmt.Sscanf(stringData,"%d/%d/%d",&gg,&mm,&aa)
```
**Nota**.
`%s` prende tutti i caratteri fino al primo carattere di spaziatuta o fino alla fine dell'input, se non ci sono spaziature. In alternativa si può specificare il numero (massimo) di caratteri da leggere (se non si incontra prima un carattere di spaziatura):
`%5s` legge una stringa di (max) 5 caratteri (caratteri di spaziatura esclusi).\
Ad esempio,
```go
fmt.Sscanf(" 1234567 ","%5s%d",&s,&i)
```
memorizzerà "12345" in s e 67 in i.
```go
Sscanf(" 12 34 567 ","%5s%d",&s,&i)
```
memorizzerà "12" in s e 34 in i.
```go
varore,min,secint
varprestring
//leggo orario (da tastiera), con i valori
//di ore, min e sec in una stringa in formato "UTC h:m:s"
ora:="UTC-11:36:21"
fmt.Sscanf(ora,"%4s%d:%d:%d",&pre,&ore,&min,&sec)
```
memorizzerà "UTC-" in pre, 11 in ore, 36 in min e 21 in sec.