Gli switch

Nella scorsa lezione abbiamo visto le strutture condizionali. L'ultimo esempio illustrato, come ricorderete, presentava una lunga serie di "else if()".

Esiste un modo migliore, più leggibile, per realizzare strutture con più comportamenti: lo switch.

Uno switch non fa altro che quello che fa un else if, in un modo più schematico.
La sintassi tipica è questa:


switch(condizione){
case "":
istruzione;
break;
}

Possiamo rivedere l'esempio dell'ultima lezione in questo modo:

Guardate la sintassi: uno switch() inizia con la condizione, dichiarata una sola volta all'inizio (nella scorsa lezione invece eravamo costretti a ripeterla per ogni elseif); nella porzione di codice tra parentesi graffe vengono valutate tutte le possibili combinazioni che interessano con la dichiarazione di un case (valore).

Il default alla fine equivale all'else dello scorso esempio: viene eseguito nel caso le altre condizioni non abbiano trovato corrispondenza, ed è ovviamente facoltativo.

Avrete notato, al termine di ogni case, il break; serve per interrompere l'esecuzione del codice, altrimenti verrebbe interpretato anche il successivo.

Se omettessimo, ad esempio, il break del mercoledì (terza condizione), verrebbe stampata anche la cella del giovedì, fino a trovare una nuova interruzione.

A volte questo può essere un comportamento desiderato, i manuali tradizionali vi toglierebbero una buona mezz'ora per farvi capire l'utilità di un break in meno, evento che in anni di programmazione ho visto con la stessa frequenza delle vittorie in trasferta del Napoli. Passiamo quindi oltre...

Vi starete chiedendo come mai PHP (e con lui gli altri linguaggi C-Like: Java, C++, Javascript) mette a disposizione gli switch quando giù ci sono gli elseif.

Anche se possiamo raggiungere l'obiettivo del programma sia con l'una che con l'altro costrutto, esiste una differenza sostanziale. Con gli elseif() possiamo valutare condizioni diverse; con gli switch sempre la stessa.

Ipotizziamo di andare al bar con l'intenzione di bere un succo di pesca-mango.
Se non troviamo il gusto desiderato, ma siamo decisi a prendere un succo di frutta, chiederemo qualcos'altro (lime-limone, banana-mela, pesca-maracuja, ecc).

Tutto sommato, abbiamo valutato sempre la stessa condizione:

if(il bar ha succo mango_pesca){
bevomango_pesca;
}
elseif(il bar ha succo banana_mela){
bevo banana_mela;
}

Possiamo definire una situazione del genere anche con uno switch.

Se invece usciamo per la pausa caffè indecisi tra un panino con prosciutto, un gelato alla frutta o una limonata, uno switch non fa al caso nostro.

Ci troviamo davanti tre tipi di condizioni diverse: la qualità del prosciutto del camioncino ambulante, la presenza di un gelataio nella zona, o la disponibilità di una limonata al bar.

Proviamo uno switch:
switch(ha_un_buon_prosciutto){

case "si":
prendi il panino;
break;
case "no":

...e adesso?? dovremmo valutare altre condizioni (il gelataio o il bar)... vero che è possibile usare degli if dentro gli switch ma in questo caso sarebbe una forzatura... meglio ricorrere agli elseif che (tra le parentesi:()) accettano qualsiasi condizione!

if(ha_un_buon_prosciutto){
prendi_panino;
}
elseif(il_gelataio_ha_gelato_frutta){
prendi_gelato;
}
elseif(il_bar_ha_spina)}
if(ha_limonata){
bevi_limonata;
}
else{
torna_in_ufficio;
}
}else{
cambia_lavoro;
}

Visto quanta libertà ci concede un elseif?

Riepilogando: usiamo uno switch quando valutiamo sempre la stessa condizione (l'esempio della scorsa lezione, sul giorno della settimana, è ideale); ricorriamo agli else e elseif quando la questione è più complessa e abbiamo più elementi che possono incidere sul comportamento.

Nel primo esempio di oggi, la discriminante erano i gusti del succo di frutta disponibili al bar, ma il termine di condizione era sempre il succo di frutta; nel secondo esempio, dovevamo valutare prodotti e luoghi (camioncino, bar, gelateria..) differenti.

Nulla ci vieta di usare switch o elseif quando vogliamo, però, per questione di efficenza e leggibilità del codice, impariamo da subito un comportamento corretto.

I cicli

Nella scorsa lezione abbiamo stampato una riga di una tabella contenente il giorno della settimana.

Ipotizziamo di voler stampare una tabella con molte righe. In HTML dovremmo digitare a manina il codice:

<tr><td bgcolor="red">Riga 1</td></tr>

In una tabella di 30 righe, dovremmo ripetere 30 volte lo stesso codice html. Con PHP è possibile automatizzare la cosa, grazie ai cicli.

La sintassi di un "ciclo for" (esistono anche i while, li vedremo in seguito) è questa:

for(inizio;condizione;iterazione){
istruzioni;
}

Per capire meglio questo strano costrutto (una volta capito il concetto, non potrete più farne a meno..) usiamo un esempio pratico.

Aprite il vostro editor testuale e salvate, nella root un file php con queste istruzioni:

In questo modo, una volta eseguito il file, avrete visualizzato a video per 9 volte questa stringa:

siamo entrati nel ciclo per la 1 volta
siamo entrati nel ciclo per la 2 volta
siamo entrati nel ciclo per la 3 volta

Cosa è successo?
Il primo termine del ciclo for, la variabile di inizio, rappresenta un contatore; la sua funzione è quella di memorizzare il numero di volte che si entra nel costrutto.

Ogni volta che usciamo da una tornata del ciclo, viene eseguita la terza istruzione tra parentesi, ovvero l'iterazione: nel nostro caso (e il più delle volte è cosi) il contatore viene incrementato di 1. L'istruzione $contatore++ è l'equivalente di $contatore=$contatore+1.

Nei linguaggi C-Like è stato introdotto l'operatore "++" per aumentare di 1 unità il valore di una variabile perché è un'istruzione molto frequente.

La seconda istruzione che abbiamo messo tra parentesi, "$contatore < 10", indica la condizione di terminazione.

Una volta usciti da una tornata del ciclo for, come abbiamo visto, viene eseguito l'incremento; il nuovo valore del contatore viene quindi confrontato con la condizione di terminazione.

Se questa risulta true, viene eseguita una nuova tornata del ciclo; altrimenti si esce.
Dato che la nostra condizione era che contatore fosse minore di 10, à stata stampata 9 volte la frase. Se volessimo stamparla 10 volte, dovremmo mettere come condizione di terminazione il segno di "<=10".

Nulla di complicato, occorre solo prendere familiarità con il costrutto.
Andiamo, con un ciclo for, a creare una tabella con 9 righe:

Nulla di diverso rispetto al primo ciclo di questa lezione. La variabile contatore può anche essere stampata a video, all'interno della stringa.

Come vedete nel ciclo ho inserito soltanto il codice delle righe, mentre i tag di inizio e fine tabella sono all'esterno.

Il motivo di questa scelta è ovvio: se avessimo messo anche il "<table>" dentro il ciclo, avremmo avuto 9 tabelle diverse, e non 1 tabella con 9 righe!

Facciamo un passo avanti. Ipotizziamo di voler stampare una tabella con righe a colori alterni.

E' una richiesta frequente su internet, pensate ad esempio alle caselle di posta elettronica lette sul web:

21/1/2012 Messaggio da web-link
21/1/2012 I hate you (e relativo virus allegato)
21/1/2012 Ciao!

 

In effetti, quando abbiamo diversi dati da visualizzare, l'alternanza di due colori rende tutto più leggibile.

Come possiamo, grazie ad un ciclo for, creare una tabella a due colori? Analizziamo le risorse, quello che sappiamo fare: sappiamo creare una tabella a N righe; il problema è che non sappiamo come far capire a PHP l'alternanza dei colori.

Conosciamo però le condizioni, i famosi IF()... ora, vi consiglio di ragionarci un attimo e provare voi stessi a trovare la soluzione. Se non riuscite, continuate a leggere questa guida.

In informatica esiste una particolare forma di variabili, i flag. Si tratta, come da traduzione, di "bandiere", ovvero di segnali di stato. Un flag può essere vero/falso, nero/bianco, 0/1 e cosi via.

Un flag può fare al caso nostro: possiamo dire a PHP di colorare una cella di verde quando la variabile-bandiera ha valore zero, o di grigio quando ha valore uno.
Il costrutto logico di un costrutto del genere è questo:


$flag_colore=0;
for(i=1;i<=10;i++){
if($flag_colore==0){
colora la cella di verde;
}
else{
colora la cella di grigio;
}
}

Non basta. In questo modo, avremmo tutte le celle colorate di verde. Sapete perché? Perché il flag non cambia mai valore: entra nel ciclo con valore zero, e di conseguenza colora la cella verde; poi, nel secondo passaggio, rimane tale e quale...

Occorre quindi cambiare il valore del flag alternativamente.

L'operazione è alla nostra portata, si tratta solo di tirar fuori un costrutto logico dalle nozioni apprese in queste tre lezioni:

Studiate bene questo codice. Non ho introdotto alcun concetto nuovo, è solo questione di logica.

Una volta entrati nel ciclo, valutiamo il valore di $flag_colore: se è pari a zero, coloriamo la cella di verde; altrimenti di grigio.

Dobbiamo inoltre ricordare di cambiare il valore del flag ogni volta, altrimenti stamperemmo sempre lo stesso colore!

Gli array

La tabella stampata grazie a questo script è graziosa quanto inutile.

Verosimilmente, in una tabella andrebbero dei dati, magari più intelligenti del "riga X"..
Ipotizziamo di voler stampare a video l'elenco delle squadre che hanno dato vita al campionato di calcio 1986-87.

All'epoca (bei tempi) giocavano 16 squadre. Sappiamo come stampare 16 righe, di colori alternati. Ma come stampare 16 righe contenenti informazioni diverse? Finora abbiamo stampato il valore del contatore..

Possiamo ricorrere a 16 variabili:

Ho volutamente omesso di continuare lo script con gli elseif() mancanti.
A questo punto, sarebbe più conveniente stampare la tabella in normale HTML, del resto i computer offrono il comodo copia/incolla.

Possibile che, nel 2012, un linguaggio di programmazione non offra una via d'uscita per stampare a video informazioni dinamiche (ovvero che cambiano ogni volta che entriamo nel ciclo), senza ricorrere a N variabili d'appoggio?

Torniamo al nostro approccio pratico. Quante volte ci troviamo, nella vita di tutti i giorni, nella situazione di valutare sottoinsiemi? Esempio banale: le squadre di calcio del campionato 1986-87.

All'epoca, dire "il numero 10", poteva dire "Maradona" come "Platini".
Dire "il numero 10 del Napoli" indicava, univocamente, Diego Maradona.

Questo esempio banale è uno dei fondamenti dell'informatica: i vettori (detti anche Matrici o, in termini di linguaggio, gli Array).

Abbiamo visto nella scorsa lezione come le variabili siano un cassetto, contenente 1 valore.
Nel corso di un programma (in linguaggi lato web la vita di un programma si riduce praticamente ad un file, fatta eccezione per le sessioni che vedremo in seguito), tale cassetto può cambiare valore (da qui il termine variabile).

Esiste tuttavia un costrutto che permette di memorizzare in una sola variabile (in un solo cassetto) più valori: gli array. Quante volte abbiamo visto, in un'officina come in una bottega di un calzolaio, degli speciali armadi con più cassetti: uno per le viti, un per i chiodi, uno per i chiodi senza testa e cosi via.

In informatica abbiamo gli Array: variabili contenenti delle sotto-variabili.
Una squadra di calcio è, a ben vedere, un array:

  • Napoli è un Array di calciatori;
  • Napoli[1] è una variabile dell'Array "Napoli" contenente il valore "Claudio Garella";
  • Napoli[10] è un'altra variabile dello stesso Array, contenente il valore "Diego Armando
  • Maradona";
  • Inter[10] è un altro Array, in questo caso ci riferiamo al numero 10 della variabile, ovvero Gianfranco Matteoli.

Ora, ipotizziamo di voler stampare nella nostra tabella l'elenco delle 16 squadre del campionato di calcio 1986-87.

Sappiamo che è possibile creare delle "multivariabili" (Array) in PHP, e che è possibile riferirsi ad un valore passando il relativo numero d'ordine:

Il codice qui sopra (attenzione: non fate caso se per alcune parti siamo andati a capo, è solo per rendere più leggibile quanto scritto, in realtà siamo sulla stessa riga, fa fede il numero a fianco di ciascuna istruzione che non dovete ricopiare nel vostro codice) stampa a video una riga per ciascuna squadra, con colori alterni.

Grazie al costrutto degli array, abbiamo inglobato in una sola variabile un elenco di 16 elementi.
Con la sintassi nomeArray[contatore] siamo risaliti, per ogni tornata del ciclo, ad un elemento della matrice.

Un momento.. la prima squadra, l'Ascoli... dove è finita?

Dovete sapere che in informatica, almeno nei linguaggi C-LIKE, i numeri iniziano da zero.

Quindi:


$elenco_squadre[1]
restituisce non il primo, ma il secondo elemento!

Cambiamo allora il ciclo in questo modo (se non avete capito il concetto, leggete quanto segue e fate delle prove verificando le possibili soluzioni):

E' cambiata anche la condizione di terminazione: se il contatore parte da zero, il ciclo termina a 15 (quindi quando è minore di 16)

L'elenco delle squadre proposto in questo script è ordinato alfabeticamente. Ipotizziamo però di avere un elenco disordinato, del tipo:

$elenco_squadre=array("Roma","Sampdoria","Avellino","Ascoli", "Como","Empoli","Fiorentina","Napoli","Juventus","Milan", "Udinese","Brescia","Atalanta","Torino","Inter","Verona");

Stampare un elenco ordinato, in questa situazione, diventa arduo. Vero che abbiamo solo 16 squadre, ma se un giorno ci trovassimo ad elencare un insieme di numeri telefonici di un'intera città?

PHP viene in nostro aiuto con una delle sue funzioni predefinite: sort().
Con questa funzione possiamo ordinare gli elementi di una matrice, secondo elenco alfabetico se sono stringhe (come nel nostro caso) o secondo valore se sono numeri.

Termina qui la terza lezione del corso PHP. Prima per� voglio darvi il link da cui scaricare il manuale. In questa settimana potete iniziare a studiarlo e trovare altre funzioni che agiscono sugli array.

Potete consultare il manuale (in inglese) da php.net: cliccate su "documentation" tra i link in alto.

Scrivete pure sul forum se avete bisogno di ulteriori chiarimenti!

Di Redazione

La nostra redazione è costantemente impegnata nel ricercare fonti attendibili e produrre contenuti informativi, guide e suggerimenti utili gratuiti per i lettori di questo sito.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

NON seguire questo link o sarai bannato dal sito!