Differences

This shows you the differences between two versions of the page.

Link to this comparison view

pub:labprog:2020-12-17 [2020/12/17 17:32] (current)
atrent created
Line 1: Line 1:
 +#  Note lezione (17/​12/​2020)
 +
 +testo (formattato male ma basta prendere il "​grezzo",​ cfr. istruzioni sul wiki stesso) lezioni precedenti sul wiki del corso: http://​sl-lab.it/​dokuwiki/​doku.php/​pub:​labprog:​home
 +
 +## Note sulle stringhe di formato (usate ad es. in Scanf)
 +
 +Prendiamo come esempio la funzione fmt.Scanf:
 +
 +```go
 +func Scanf(format string, a ...interface{}) (n int, err error)
 +   
 +/*Scanf scans text read from standard input,
 +storing successive space-separated values into
 +successive arguments as determined by the format [...].*/
 +
 +```
 +
 +Il primo argomento di questa funzione è una "​stringa di formato"​. La stringa di formato descrive esattamente quello che ci si aspetta di leggere come input (o scrivere in output, nel caso di una stampa).
 +
 +
 +Ad esempio, supponiamo di voler leggere una data dal linea di comando (esattamente come viene richiesto dall'​esercizio 1 di oggi) nel seguente formato: `gg/​mm/​aaaa`.
 +
 +### Lettura corretta ​
 +
 +```go
 +fmt.Sscanf(os.Args[1],​ "​%d/​%d/​%d",​ &gg, &mm, &aa)
 +fmt.Println(gg,​mm,​aa)
 +```
 +
 +```bash
 +./main 15/09/2040
 +15 9 2040 # notare che lo 0 del 9 scompare
 +          # leggere sez.Lunghezza e precisione in output
 +```
 +
 +### Spazi bianchi
 +
 +Vediamo invece la seguente implementazione:​
 +
 +```go 
 +fmt.Sscanf(os.Args[1],​ "%d / %d / %d", &gg, &mm, &aa)
 +fmt.Println(gg,​mm,​aa)
 +```
 +
 +La differenza rispetto a prima è che sono stati inseriti degli spazi bianchi all'​interno della stringa di formato. Se alla riga di comando forniamo lo stesso input di prima, otteniamo un risultato "​strambo":​
 +
 +```bash ​
 +./main 15/09/2040
 +15 0 0
 +```
 +
 +**Attenzione**:​ lo spazio bianco è un carattere, esattamente come tutti gli altri, quindi viene utilizzato come separatore. ​
 +
 +Allora ci si potrebbe chiedere: mettendo gli *stessi* spazi bianchi anche dentro l'​input,​ la lettura andrebbe a buon fine? *(leggi la prossima sezione)*
 +
 +### Le virgolette ​
 +
 +```
 +./main 15 / 09 / 2040
 +15 0 0
 +```
 +
 +No, nonstante l'​aggiunta degli spazi, la lettura non viene effettuata correttamente. ​
 +
 +Questo perchè gli spazi sono un separatore anche per gli argomenti a linea di comando. Infatti, se aggiungiamo i seguenti comandi al nostro programma:
 +
 +```go 
 +fmt.Println("#​argomenti:",​len(os.Args))
 +for pos,val := range os.Args {
 +    fmt.Printf("​argomento %d: %s\n", pos, val)
 +}
 +```
 +Otteniamo:
 +```
 +15 0 0
 +#argomenti: 6
 +argomento 0: ./main
 +argomento 1: 15
 +argomento 2: /
 +argomento 3: 09
 +argomento 4: /
 +argomento 5: 2040
 +```
 +
 +Quindi, per poter leggere "​correttamente"​ la data, tutti i valori dovranno essere contenuti all'​interno dell'​argomento #1. Per fare ciò mettiamo tra virgolette la data intera nella linea di comando (esattamente come se fosse una stringa) :
 +
 +```
 +./main "15 / 09 / 2040"
 +15 9 2040
 +#argomenti: 2
 +argomento 0: ./main
 +argomento 1: 15 / 09 / 2040
 +```
 +
 +### Utilizzare `-` come separatore
 +
 +Supponiamo ora di avere come separatore il simbolo `-` al posto del simbolo `/`.
 +
 +L'​istruzione corretta diventa quindi:
 +
 +```go 
 +fmt.Sscanf(os.Args[1],​ "​%d-%d-%d",​ &gg, &mm, &aa)
 +```
 +
 +E abbiamo come effetto:
 +
 +``` 
 +./main 15-09-2040
 +15 9 2040
 +```
 +
 +**Attenzione**:​ se per sbaglio fosse stato omesso il simbolo `-` all'​interno della stringa di formato, si sarebbero ottenuti risultati poco piacevoli:
 +
 +```go 
 +//ometto -
 +fmt.Sscanf(os.Args[1],​ "%d %d %d", &gg, &mm, &aa)
 +```
 +
 +``` 
 +./main 15-09-2040
 +15 0 0
 +#argomenti: 2
 +argomento 0: ./main
 +argomento 1: 15-09-2040
 +```
 +
 +Questo succede perchè il primo argomento non rispetta la stringa di formato *(infatti, il 15 viene letto, mentre tutto il resto viene scartato dal momento che ci si aspetta che ci sia lo spazio come separatore)*.
 +
 +
 +
 +### Tabellina specificatori
 +`%v` stampa una struct (senza nomi dei campi)
 +`%+v` stampa una struct con nomi dei campi 
 +`%t` bool
 +`%d` intero
 +`%c` stampa carattere (runa)
 +`%x` valore esadecimale
 +`%f` float 
 +`%s` stringa
 +
 +
 +### Lunghezza e precisione in output
 +
 +Formattazione output: `%[lunghezza_min][.precisione]<​specificatore>​`
 +
 +- `lunghezza`: ​ numero minimo di caratteri da stampare. Se il numero fornito è più corto, vengono aggiunti degli spazi bianchi **a sinstra**. Se è più lungo **non** viene tagliato.
 +
 +    Esempio: ​
 +    ```go 
 +    //mi aspetto un numero da almeno 2 cifre
 +    fmt.Printf("​%2d\n",​ 1)
 +    fmt.Printf("​%2d\n",​ 10)
 +    fmt.Printf("​%2d\n",​ 100)
 +
 +    fmt.Printf("​%2f\n",​ 1.0)
 +    fmt.Printf("​%2f\n",​ 10.0)
 +    fmt.Printf("​%2f\n",​ 100.0)
 +
 +    ```
 +    ```bash
 +     ​1 ​       #il primo carattere è bianco
 +    10
 +    100
 +    ​
 +    1.000000 ​ #qua non accade
 +    10.000000
 +    100.000000
 +    ```
 +
 +- `precisione` : nel caso di interi è equivalente alla lunghezza, con la differenza che al posto degli spazi bianchi vengono aggiunti degli zeri a sinistra:
 +
 +    ```go 
 +    fmt.Printf("​%.3d\n",​ 1)
 +    fmt.Printf("​%2.3d\n",​ 1)
 +    fmt.Printf("​%4.3d\n",​ 1)
 +    ```
 +    ```bash ​
 +    001
 +    001
 +     001 # non è sbagliato, lo spazio bianco a sx
 +         # c'è perchè si devono stampare almeno 4
 +         # caratteri ​
 +    ```
 +    ​
 +    Nel caso di float, invece, indica il numero di cifre da stampare dopo la virgola ​
 +    ​
 +    ```go
 +    fmt.Printf("​%2.0f\n",​ 10.42)
 +    fmt.Printf("​%2.1f\n",​ 10.42)
 +    fmt.Printf("​%2.3f\n",​ 10.42)
 +    ```
 +    ​
 +    ```
 +    10
 +    10.4
 +    10.420
 +    ```
 +
 +---
 +    ​
 +Tornando velocemente all'​esempio della data, eravamo rimasti con: 
 +    ​
 +```go
 +fmt.Sscanf(os.Args[1],​ "​%d/​%d/​%d",​ &gg, &mm, &aa)
 +fmt.Println(gg,​mm,​aa)
 +```
 +
 +```bash
 +./main 15/09/2040
 +15 9 2040 
 +```    ​
 +Se al posto di `9` volessimo stampare `09`, dovremmo modificare il codice come segue:
 +
 +```go
 +fmt.Printf("​%.2d %.2d %d\n", gg, mm , aa)
 +```
 +```
 +./main 15/09/2040
 +15 09 2040
 +```
 +
 +
 +
 +
 +
 +.
 +
 +
 +
 +
  
pub/labprog/2020-12-17.txt · Last modified: 2020/12/17 17:32 by atrent
CC Attribution-Share Alike 4.0 International
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0