if (*clock).sec==0 && ((*clock).hour!=0 ||(*clock).min!=0 )
```
-Countdown:evitare i doppi controlli
```go
func countdown (clock *Clock) {
if (*clock).sec==0 && ((*clock).hour!=0 ||(*clock).min!=0 ){ <<<<<<<<<<
func main() {
for {
countdown(&clock)
.....
if clock.hour==0 && clock.min==0 && clock.sec==0 { <<<<<<<<<<
break
}
```
-Countdown d.c. <<<
divisione dei compiti (ad es. downMin aggiorna anche i secondi)
```go
func downHour(time Clock) {
time.min = 59
time.hour--
}
```
-Dado:cosa fa?
```go
for i := 0; i < n; i++ {
lancio = rand.Intn(NFACCE) + 1
frequenza[lancio]++
for i:=0; i<n; i++ {
fmt.Printf("%d:%d (%d%%)\n", i, frequenza[i], frequenza[i]*100/n)
}
}
```
---
## Note iniziali
- Go test: vedi indicazioni in Lab06.md
### Interruzioni forzate
Ci sono tre diversi livelli in cui è possibile dare istruzioni di **interruzione forzata**, da non confondere assolutamente:
- a livello di **ciclo for** con l'istruzione "**break**": <ins>l'esecuzione del programma prosegue</ins> con l'istruzione subito dopo la chiusa graffa del for;
- a livello di **funzione** con un'istruzione di "**return**": <ins>l'esecuzione del programma prosegue</ins> nella funzione chiamante con l'istruzione in cui la funzione è stata chiamata, o, se è completata, con quella subito dopo;
- a livello di **programma**, e quindi di funzione main, con l'istruzione "**return**" o invocando la funzione "**os.Exit**": <ins>l'esecuzione del programma termina</ins>.
---
### Funzioni e I/O
Quando volete implementare una parte della soluzione attraverso una **funzione**, chiedetevi:
1. se la funzione vi serve principalmente per **spezzare il codice** in moduli più piccoli, che potreste mettere insieme senza modifiche o quasi in un unico main;
1. se la funzione deve **ricevere** da e / **o fornire** al resto del programma dei **valori**.
Nel **primo caso**, tra le parti che potete voler impacchettare in una funzione potrebbe esserci anche la **lettura** dell'input e/o la **stampa** dell'output.
Nel **secondo caso**, invece, è meglio passare valori alla funzione per mezzo di **parametri**, facendo leggere altrove i dati dall'esterno (tipicamente nel main). Analogamente è meglio passare per mezzo di **valori di ritorno** (*return values*) i risultati calcolati dalla funzione, delegandone, tipicamente al main, la eventuale stampa.
In generale, cercate di evitare funzioni con tutti e due i ruoli (ma, come sempre, ci possono essere eccezioni).
E in ogni caso, in generale evitate funzioni con solo un paio di righe di codice o una sola. In questi casi mettete l'istruzione, o le istruzioni, direttamente al posto dell'invocazione di funzione (ma, come sempre, ci possono essere eccezioni).
---
### La slice os.Args
Un programma ha accesso agli argomenti passati da linea di comando per mezzo della slice `os.Args`, una variabile del pacchetto `os`.
In `os.Args` vengono salvati automaticamente, come stringhe, gli argomenti passati da linea di comando a un programma.
Il primo elemento di questa slice, os.Args[0], contiene sempre il path del programma, mentre os.Args[1:] contiene gli argomenti veri e propri passati al programma da linea di comando.
Ad esempio, se lancio l'esecuzione di myProgram così:
```
./myProgram arg1 arg2 arg3
```
os.Args conterrà "arg1", "arg2", e "arg3", in particolare "arg1" in os.Args[1], "arg2" in os.Args[2], e così via.
---
## Brevi richiami sulle slice
#### Dichiarazione di una slice (viene creata una slice nulla, cioè nil):
sintassi:
```go
varnomeSlice[]type
```
esempio:
```go
varmySlice[]int
```
Nota. Le funzioni builtin len, cap e append funzionano anche con slice nil.
#### Creazione/inizializzazione di una slice con lunghezza/capacità fissate
sintassi:
```go
nomeSlice:=make([]type,length,capacity)
nomeSlice:=make([]type,length)//la capacità può non essere specificata
nomeSlice:=[]type{}// tra {} ci può essere una lista di valori
```
esempi:
```go
mySlice:=make([]int,4,5)
mySlice:=make([]int,4)
mySlice:=[]int{}
mySlice:=[]int{1,2,3,4}
```
#### Stampa di una slice
```
mySlice := []int{1, 2, 3, 4}
fmt.Println(mySlice)
```
produce in output:\
[1 2 3 4]
#### Subslicing
```go
mySlice[3]//elemento di indice 3
mySlice[:3]//gli elementi fino a quello di indice 3 escluso
mySlice[3:]//gli elementi da quello di indice 3 incluso all'ultimo
mySlice[3:7]//gli elementi da quello di indice 3 a quello di indice 6 (cioè a quello di indice 7 escluso)
```
#### Funzioni built-in per slice
(vedi documentazione packages, sotto builtin)
```go
funcappend(nomeSlice[]Type,elems...Type)[]Type
```
esempi:
```go
mySlice=append(aSlice,elem1,elem2)
mySlice=append(aSlice,anotherSlice...)// i ... fanno parte della sintassi
```
```go
funccopy(dest,src[]Type)int
```
Nota: se dest è più piccola di src, solo una parte verrà copiata.
esempio:
```go
//esempio con lunghezze uguali:
myCopy=make([]int,len(mySlice))
copy(myCopy,mySlice)
```
---
## Esercizi Go per il Lab 07 - slice e array e bufio
### Esercizi di avvio all'uso delle slice
### Esercizio 1 - progettazione: memorizzazione in slice vs elaborazione/stampa immediata
Problemi con domande sull'uso o meno di slice, a [questo link](https://forms.gle/rPqGNkNyjuMFmiMRA).
Rispondere alle domande del form.
### Esercizio 2 - implementazione
Scrivete i programmi per i problemi n. 2, 7, 8, 10, 12 dell'esercizio 1 e caricateli su upload (con i nomi es2.go, es7.go, es8.go, ecc.).
### Esercizio 3 - comprensione
Esercizio di associazioni frammenti di codice - descrizioni di operazione su slice, a questo [link](https://forms.gle/QWYktEU6G9dyD5FN6)(esercizio propedeutico all'esercizio 4).
### Esercizio 4 - operazioni su slice
Scrivere un programma usoLeSlice.go che
- legge da linea di comando una lista di almeno 3 parole;
- legge da standard input un'altra lista di parole (anche almeno 3).
Quindi fa le seguenti operazioni e man mano stampa il risultato ottenuto:
1. delle due liste fa un'unica lista (slice), da elaborare e a cui, se serve, ci riferiremo con "mySlice"
2. mette in ordine alfabetico (lessicografico) la slice ottenuta (usare una funzione di libreria) e poi la stampa
3. cancella l'ultima parola dalla slice
4. rimuove dalla slice gli elementi di indice dal 2 (incluso) al 4 (escluso)
5. crea una nuova slice con "aa", "bb" e "cc"
6. la inserisce in posizione 1 della vecchia slice (mySlice)
7. legge una nuova parola e la inserisce in posizione 2 della slice mySlice
8. legge una nuova parola e la inserisce in fondo alla slice mySlice
9. estende la slice mySlice con una nuova slice di lunghezza 2 (di stringhe vuote)
10. inserisce alla posizione 3 di mySlice una nuova slice di lunghezza 3 (di stringhe vuote)
11. copia in una nuova slice la slice mySlice ottenuta fin qui
12. dalla copia rimuove l'ultimo elemento e stampa sia la slice mySlice che la copia.
Esempio di esecuzione:
```
$ ./usoLeSlice.go uno due tre
scrivi almeno 3 parole (seguite da ctrl D)
4 5 6 7
1. [uno due tre 4 5 6 7]
2. [4 5 6 7 due tre uno]
3. [4 5 6 7 due tre]
4. [4 5 due tre]
5. [aa bb cc]
6. [4 aa bb cc 5 due tre]
scrivi una parola: pos2
7. [4 aa pos2 bb cc 5 due tre]
scrivi una parola: lastPos
8. [4 aa pos2 bb cc 5 due tre lastPos]
9. [4 aa pos2 bb cc 5 due tre lastPos ]
10. [4 aa pos2 bb cc 5 due tre lastPos ]
11. [4 aa pos2 bb cc 5 due tre lastPos ]
12. [4 aa pos2 bb cc 5 due tre lastPos ]
[4 aa pos2 bb cc 5 due tre lastPos ]
```
nomefile: usoLeSlice.go
### Esercizio 5 - da stringhe a slice
(uso delle funzioni strings.Fields, strings.Split e strings.SplitAfter e delle conversioni []byte() e []rune())
Scrivere una programma `strings2slice.go` che legge da linea di comando:
- una stringa in formato CSV (del tipo: \<nome\>,\<cognome\>,\<matricola\>), ne estrae i valori salvandoli in una slice e stampa la slice;
- della stessa stringa estrae i valori compresa la virgola separatore salvandoli in una slice e stampa la slice;
- una frase tra "" di parole separate anche da più spazi e tab, ne estrae le parole salvandole in una slice e stampa la slice;
- un numero intero non negativo e stampa la slice dei codici ASCII delle cifre che lo formano, nello stesso ordine da sinistra a destra;
- una stringa di lettere accentate e stampa la slice dei codici unicode delle lettere che la formano;
- un orario nel formato h:m:s, ne estrae ore, minuti e secondi salvandoli in una slice e stampa la slice.
## Esercizi sulle slice e su bufio
(os.Arg, slice restituite da funzioni di libreria, slice create nel programma)
### Esercizio - Quadrati (con TEST)
Scrivere una programma `quadrati.go` che legge da linea di comando una sequenza di numeri interi non negativi e stampa solo quelli che sono dei quadrati (1, 4, 9, ecc.). Il programma deve essere dotato di una funzione
`isSquare(n int) bool`
che restituisce true se *n* è un quadrato, false altrimenti.
nomefile: quadrati.go
### Esercizio - Ordini (con TEST)
Scrivere un programma ordini.go che legge da standard input una serie di stringhe che descrivono ordini nel formato
`prezzo#quantità#sconto`
e stampa il totale finale da pagare.
Prezzo, quantità e sconto sono float; prezzo indica il prezzo unitario del prodotto, quantità indica la quantità acquistata e sconto è lo sconto applicato per quel prodotto, espresso come float tra 0 e 1 (ad esempio 0.2 indica uno sconto del 20%).
Il programma termina la lettura quando incontra EOF (ctrl D su riga nuova).
nomefile: ordini.go
### Esercizio - Stampa alternata (con TEST)
Scrivere un programma stampaAlternata.go che legge da standard input del testo su più righe (terminato da EOF) e stampa prima le righe pari e poi le righe dispari (considerate la prima riga del testo la riga 1 (e non 0)).
nomefile: stampaAlternata.go
### Esercizio - Polinomio (con TEST)
Scrivere un programma `polinomio.go` che legge da standard input una riga che contiene dei numeri a, b, ....
Il programma calcola il valore in x del polinomio\
a + bx + cx^2 + dx^3 ....\
corrispondente alla sequenza dei numeri letti tranne l'ultimo; l'ultimo valore della sequenza è il valore di x.
Ad esempio,
3 2 0 7 5
corrisponde al polinomio 3 + 2x + 7x^3 da valutare per x = 5
nomefile: polinomio.go
### Esercizio - extractions (con TEST)
Scrivere un programma `extractions.go` con due funzioni:
-`estraiPari(in []int) (out []int)` che prende una slice di interi e ne restituisce una che contiene solo i numeri di quella in ingresso che sono numeri pari.
-`rimuoviMultipli(m int, in []int) (out []int)` che prende un intero e una slice di interi e ne restituisce una senza i multipli del numero passato di quella in ingresso. Es.: `rimuoviMultipli(5, in)` restituisce, a partire da `in`, una slice senza i multipli di 5.
Nota: non ci sono specifiche per la funzione main.
nomefile: extractions.go
## Esercizi su array
### Esercizio - giorni della settimana
Scrivere un programma `giornoSettimana.go`, dotato di un array giorniDellaSettimana\
che legge da linea di comando il nome del giorno della settimana del 1° gennaio di un dato anno. Se il giorno non è fra "lun", "mart", "merc", "giov", "ven", "sab", "dom", il programma avvisa e termina. Altrimenti poi accetta da standard input dei numeri interi (tra 1 e 365), corrispondenti a giorni di quell'anno, e per ciascuno stampa il giorno della settimana corrispondente. Il programma termina quando l'utente digita -1.
nomefile: giornoSettimana.go
### Esercizio - conteggio delle lettere in un testo (con TEST)
Scrivere un programma `contaLettere.go` che legge un testo (da stdin) e stampa quante volte (anche 0) appare nel testo ciascuna lettera minuscola dell'alfabeto ('a'-'z').