Ciao a tutti e bentornati! Sino ad ora ci siamo preoccupati di fare una carrellata quanto più completa riguardo i concetti fondamentali di cui abbiamo bisogno per approcciarci all'utilizzo delle strutture condizionali. Abbiamo quindi introdotto il concetto di struttura condizionale, delineando le varie situazioni che ci si potrebbero presentare. Successivamente ci siamo preoccupati di delineare i tratti principali dell'algebra booleana, analizzando l'utilizzo delle variabili booleane e degli operatori booleani.
Un concetto che vale la pena ribadire è che le strutture condizionali, dette anche di controllo del flusso, servono a modificare il normale flusso di esecuzione del programma.
Siccome per imparare a programmare non basta leggere, andiamo ad analizzare qualche esempio pratico, in modo da vedere in azione i concetti che abbiamo analizzato sino ad ora. Va detto che, nel fare la disamina di alcuni esempi, darò per scontati gli aspetti teorici e pratici riguardanti le variabili, puntando il focus sugli aspetti riguardanti le strutture di selezione.
Caso 1: strutture di selezione annidate
Una prima domanda che ci si potrebbe porre è quella riguardante il caso delle strutture di selezione annidate. Ci si potrebbe infatti chiedere se all'interno di un if si possa innestare un secondo if.
La risposta è sì.
Vediamo bene come.
// controlla che n1 sia maggiore o uguale di n2 if (n1 >= n2) { // controlla che n1 sia maggiore o uguale di n3 if (n1 >= n3) { largest = n1; } else { largest = n3; } } else { // controlla che n2 sia maggiore o uguale di n3 if (n2 >= n3) { largest = n2; } else { largest = n3; } } System.out.println("Largest Number: " + largest);
Questo esempio potrebbe sembrare complesso all'apparenza, ma leggendo attentamente, ci accorgiamo che il compito che assolve è alquanto semplice: si preoccupa di trovare la variabile che ha il valore massimo all'interno di un insieme di tre variabili.
Per fare questo, il ragionamento è il seguente: per essere il massimo, un valore deve essere maggiore degli altri due. Succede quindi che si controlla se n1 è maggiore di n2. Se questo è vero, allora si controlla che n1 sia maggiore anche di n3. Nel caso che anche due condizioni siano vere, allora si valorizza la variabile largest con il valore contenuto in n1.
Se n1 è minore di n2, sappiamo che n1 non potrà essere il massimo. Rimane quindi da effettuare il controllo con n2 e n3. Se n2 è maggiore di n3, allora n2 è il massimo tra le tre variabili. In caso contrario, il massimo è n3.
Possiamo facilmente notare che è possibile innestare più if uno dentro l'altro. Questo è concesso, anche se non sempre incoraggiato.
Nota di sintassi: le parentesi graffe
Tecnicamente, Java ci consente di omettere le parentesi graffe sia dai blocchi if che dai blocchi else, a patto che contengano solo e soltanto un'istruzione e non di più.
Spesso questa pratica è utilizzata, e ammetto che io stesso lo faccio: Va detto che, a mio parere, si va a perdere di leggibilità e di chiarezza. Ovviamente, si va a guadagnare in compattezza del codice. Nel caso di if innestati, detti anche nested if, io consiglio di utilizzarle sempre.
Caso 2: strutture di selezione con condizioni composte
Un altro caso interessante da analizzare è quello in cui si utilizzano gli operatori booleani all'interno delle condizioni. Il classico esempio che si può analizzare è quello classico in cui si vuole controllare che un dato numero rientri in un range. Si pensi, per esempio, ad un software per fare valutazioni statistiche sulle prestazioni scolastiche di una classe.
Ipotizziamo di voler contare quanti sono i voti sufficienti su una scala da 1 a 10, quindi con valore maggiore o uguale di sei.
Vediamo quindi come poter fare, ipotizzando di aver già dichiarato e inizializzato una variabile denominata voto.
int contatore = 0; if(voto >= 6 && voto <= 10){ contatore = contatore + 1; }
L'idea è quindi quella che un voto va considerato sufficiente se e solo se è maggiore o uguale di 6 e contemporaneamente minore o uguale di 10. Ad un primo tentativo, qualcuno potrebbe sostenere che il semplice controllo voto >= 6 sia sufficiente. Il problema sorge però nel caso in cui ci sia un errore di inserimento e un voto maggiore di dieci venga inserito. La nostra applicazione lo considererebbe sufficiente, pur non essendo un voto valido. Ci si troverebbe quindi a considerare lecita una situazione che andrebbe gestita come problematica.
Caso 3: condizione con negazione
Spesso, potrebbe essere comodo utilizzare condizioni che contengono al loro interno una negazione. Questo potrebbe essere per motivi diversi. Potrebbe trattarsi di comodità di sviluppo oppure di mera leggibilità.
Vediamo un esempio. Come caso d'uso possiamo mantenere sempre quello dell'analisi dei voti. Ipotizziamo quindi di voler controllare che un voto sia valido. Una soluzione potrebbe essere simile a quella prodotta prima. Una soluzione di gran lunga più leggibile e semplice, a mio parere, è la seguente.
boolean votoValido = voto >= 6 && voto <= 10; if(!votoValido){ //gestisci errore }
Notiamo quindi che qui il codice è molto semplice da capire. In linguaggio naturale, la condizione può essere letta come "if not votoValido", che tradotto in linguaggio naturale italiano, può essere "se il voto non è valido". Capiamo quindi che l'if verrà eseguito solo se il voto non è valido. Questo è il caso in cui l'utilizzo di una variabile booleana semplifica di gran lunga lo sviluppo del codice.
Conclusioni
Questa breve disamina ci lascia intuire qualche aspetto saliente. In particolare, vediamo come si possano combinare gli operatori per formare espressioni complesse.
É importante, in queste situazioni come in tutto il resto della programmazione, prestare attenzione all'indentazione del codice. Il rischio è quello di scrivere un codice decisamente complicato da leggere, se non si inseriscono le dovute spaziature ad inizio riga.
Vedremo più avanti che esiste una valida alternativa all'utilizzo massivo di costrutti if: lo switch statement.
Va precisato e ribadito il fatto che l'analisi fatta non è assolutamente da intendersi come esaustiva. L'idea è quella di dare prima gli strumenti fondamentali per iniziare a scrivere codice, e successivamente di approfondire alcuni aspetti peculiari.
Per esercitarsi, può essere utile risolvere il seguente esercizio:
Scrivere un programma PariPiccolo che chiede all’utente di inserire un numero intero e visualizza il messaggio "Pari e Piccolo" se il numero `e pari ed `e compreso tra 0 e 100, altrimenti stampa il messaggio "Non e’ pari e piccolo". (Nota: questo programma si pu`o realizzare usando if-else annidati o espressioni booleane. Provate entrambe le versioni.)
L'esercizio è stato preso da questo documento.