# 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